1

I am a beginner with Pandas and Matplotlib and I have some questions about formatting plots when using pandas. I have the following code for an area plot:

import pandas as pd
from matplotlib import pyplot as plt

ax= wind_data.plot.area()
plt.legend(loc='center left', bbox_to_anchor= (1.0, 0.5))
plt.grid(False)
ax.set_facecolor("white")
ax.set_xlabel("Time of day")
ax.set_ylabel("Power in kW")
ax.set_xlim(0,24)
ax.set_ylim(0,50)

Now I want to change the following aspects:

  • The values on the x axis are times of the day. They should be displayed beginning from 00:00 - 24:00. So for every hour there should be an entry. The entries should be written vertically (not horizontally) due to lack of space
  • When I export the png-file there is a grey box around the plot. This should not be the case. Instead there should be a thin black line that serves as the rim
  • I would like to have some horizontal line at every entry of the y-axis. This line should not be so strong but rather somehow transparent such that you can see it, without being dominant.

Is it possible to do this with Matplotlib(or any other library for python)?

EDIT: Here you have the input data:

Building 1  Building 2  Building 3  Building 4  Building 5
7.04    7.04    7.04    7.04    7.04
6.36    6.36    6.36    6.36    6.36
6.4     6.4     6.4     6.4     6.4
6.1     6.1     6.1     6.1     6.1
5.88    5.88    5.88    5.88    5.88
6.18    6.18    6.18    6.18    6.18
6.16    6.16    6.16    6.16    6.16
5.82    5.82    5.82    5.82    5.82
5.28    5.28    5.28    5.28    5.28
4.82    4.82    4.82    4.82    4.82
4.18    4.18    4.18    4.18    4.18
4.02    4.02    4.02    4.02    4.02
4.08    4.08    4.08    4.08    4.08
4.24    4.24    4.24    4.24    4.24
6.24    6.24    6.24    6.24    6.24
8.44    8.44    8.44    8.44    8.44
8.72    8.72    8.72    8.72    8.72
8.06    8.06    8.06    8.06    8.06
7.16    7.16    7.16    7.16    7.16
6.52    6.52    6.52    6.52    6.52
7.16    7.16    7.16    7.16    7.16
7.88    7.88    7.88    7.88    7.88
8.44    8.44    8.44    8.44    8.44
8.56    8.56    8.56    8.56    8.56

EDIT: Error message when using JohanC's solution code in Jupyter

AttributeError                            Traceback (most recent call last)
<ipython-input-5-51251d64e3e0> in <module>()
     21 ax.set_xlim(1, 24)
     22 ax.set_ylim(0, 50)
---> 23 plt.xticks(wind_data.index, labels=[f'{h:02d}:00' for h in wind_data.index], rotation=90)
     24 plt.grid(axis='y', alpha=.4)
     25 plt.tight_layout()

C:\Users\wi9632\AppData\Local\Continuum\Anaconda3\lib\site-packages\matplotlib\pyplot.py in xticks(*args, **kwargs)
   1704     if len(kwargs):
   1705         for l in labels:
-> 1706             l.update(kwargs)
   1707 
   1708     return locs, silent_list('Text xticklabel', labels)

C:\Users\wi9632\AppData\Local\Continuum\Anaconda3\lib\site-packages\matplotlib\text.py in update(self, kwargs)
    241         """
    242         bbox = kwargs.pop('bbox', None)
--> 243         super(Text, self).update(kwargs)
    244         if bbox:
    245             self.set_bbox(bbox)  # depends on font properties

C:\Users\wi9632\AppData\Local\Continuum\Anaconda3\lib\site-packages\matplotlib\artist.py in update(self, props)
    883         try:
    884             ret = [_update_property(self, k, v)
--> 885                    for k, v in props.items()]
    886         finally:
    887             self.eventson = store

C:\Users\wi9632\AppData\Local\Continuum\Anaconda3\lib\site-packages\matplotlib\artist.py in <listcomp>(.0)
    883         try:
    884             ret = [_update_property(self, k, v)
--> 885                    for k, v in props.items()]
    886         finally:
    887             self.eventson = store

C:\Users\wi9632\AppData\Local\Continuum\Anaconda3\lib\site-packages\matplotlib\artist.py in _update_property(self, k, v)
    876                 func = getattr(self, 'set_' + k, None)
    877                 if func is None or not six.callable(func):
--> 878                     raise AttributeError('Unknown property %s' % k)
    879                 return func(v)
    880 

AttributeError: Unknown property labels
PeterBe
  • 700
  • 1
  • 17
  • 37

1 Answers1

1

Here is an example using matplotlib. Now with the data from the updated question.

For the xticks, the tick positions and labels can be set with plt.xticks()``, which also accepts a rotation angle. To get a black border, it seems the linewidth needs to be set via plt.figure, while the edgecolor is a parameter to plt.savefig.

plt.grid has parameters to show grid lines in one or both directions. An alpha value can be set to make these lines less or more prominent.

import pandas as pd
from matplotlib import pyplot as plt
%matplotlib inline

columns = ['Building 1', 'Building 2', 'Building 3', 'Building 4', 'Building 5']
power_values = [[7.04, 7.04, 7.04, 7.04, 7.04], [6.36, 6.36, 6.36, 6.36, 6.36], [6.4, 6.4, 6.4, 6.4, 6.4],
                [6.1, 6.1, 6.1, 6.1, 6.1], [5.88, 5.88, 5.88, 5.88, 5.88], [6.18, 6.18, 6.18, 6.18, 6.18],
                [6.16, 6.16, 6.16, 6.16, 6.16], [5.82, 5.82, 5.82, 5.82, 5.82], [5.28, 5.28, 5.28, 5.28, 5.28],
                [4.82, 4.82, 4.82, 4.82, 4.82], [4.18, 4.18, 4.18, 4.18, 4.18], [4.02, 4.02, 4.02, 4.02, 4.02],
                [4.08, 4.08, 4.08, 4.08, 4.08], [4.24, 4.24, 4.24, 4.24, 4.24], [6.24, 6.24, 6.24, 6.24, 6.24],
                [8.44, 8.44, 8.44, 8.44, 8.44], [8.72, 8.72, 8.72, 8.72, 8.72], [8.06, 8.06, 8.06, 8.06, 8.06],
                [7.16, 7.16, 7.16, 7.16, 7.16], [6.52, 6.52, 6.52, 6.52, 6.52], [7.16, 7.16, 7.16, 7.16, 7.16],
                [7.88, 7.88, 7.88, 7.88, 7.88], [8.44, 8.44, 8.44, 8.44, 8.44], [8.56, 8.56, 8.56, 8.56, 8.56]]
wind_data = pd.DataFrame(power_values, index=range(1, 25), columns=columns)
fig = plt.figure(linewidth=1, figsize=(7, 5))
ax = wind_data.plot.area(ax=plt.gca(), color=plt.get_cmap('Set1').colors)
plt.legend(loc='center left', bbox_to_anchor=(1.0, 0.5))
ax.set_facecolor("white")
ax.set_xlabel("Time of day")
ax.set_ylabel("Power in kW")
ax.set_xlim(1, 24)
ax.set_ylim(0, 50)
plt.xticks(wind_data.index, labels=[f'{h:02d}:00' for h in wind_data.index], rotation=90)
plt.grid(axis='y', alpha=.4)
plt.tight_layout()
plt.savefig('wind_data.png', edgecolor='black', dpi=300)
plt.show()

example plot

PS: If your Python version is older than 3.6, replace f'{h:02d}:00' by '%02d:00' % h.

JohanC
  • 71,591
  • 8
  • 33
  • 66
  • Thanks Johan for your answer. Unfortunately I get many errors when I use your posted code with Jupyter. I edited the original post and added the input data. Maybe this helps you. – PeterBe Jan 02 '20 at 09:59
  • To me it works just fine, also inside a notebook. I updated the code with your new data, so I needed 24 instead of 25 values. Please add the error messages to the question if you still encounter problems. – JohanC Jan 02 '20 at 22:41
  • Hi Johan, thanks for your effort. I tried it again in Jupyter Notebooks and I still get an Error message. I copied the error message into my previous post. Maybe this helps you. – PeterBe Jan 03 '20 at 09:08
  • 1
    This seems to indicate you have a quite old version of matplotlib (older than 1.5, current version is 3.1.1). Could you try to upgrade? Apart from that, I'm using f-strings, something new in Python 3.6 to easily integrate numbers into strings. – JohanC Jan 03 '20 at 17:21
  • You can use `labels=['%02d:00' % h for h in wind_data.index]` if the Python version is older than 3.6. – JohanC Jan 04 '20 at 01:56
  • Now I reinstalled Anaconda and the figure looks good :-). Thanks a lot Johan. Still I have a further quesiton. In your example you manually tipped in every entry of the time series. This is quite unconvenient if you have multiple time series with many entries. How can I read the values for the variables "columns = " and "power_values = " from a file? – PeterBe Jan 05 '20 at 16:35
  • 1
    If your files are organized as csv, you could call `wind_data = pd.read_csv("filename.csv") `. See [docs](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html) or [this post](https://www.shanelynn.ie/python-pandas-read_csv-load-data-from-csv-files/). There is something similar to [read Excel files](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_excel.html) provided the files are structured as a header line and values. – JohanC Jan 05 '20 at 16:52
  • Thanks a lot Johan for your help and effort. Maybe one last question (to learn something and not just copy and paste the code). What is the difference between fig, ax and plt. How do I know, which one to choose. – PeterBe Jan 05 '20 at 18:25
  • 1
    "plt" is the library. "fig" is a variable to represent one division in a plot. "ax" is another variable that mainly controls how the screen-x-y is mapped to x and y coordinates. See https://stackoverflow.com/questions/37970424/what-is-the-difference-between-drawing-plots-using-plot-axes-or-figure-in-matpl There is also plt.gca() to "get the current axes" and plt.gcf() to "get the current figure". Often plt.something gets converted internally to plt.gca().something. So, there is a lot of overlap and it is not always easy to know which functionality is where. – JohanC Jan 05 '20 at 18:52
  • Thanks for your help Johan. I upvoted and accepted your answer. – PeterBe Jan 06 '20 at 10:25