Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matplotlib showing x-tick labels overlapping

Have a look at the graph below: enter image description here

It's a subplot of this larger figure: enter image description here

I see two problems with it. First, the x-axis labels overlap with one another (this is my major issue). Second. the location of the x-axis minor gridlines seems a bit wonky. On the left of the graph, they look properly spaced. But on the right, they seem to be crowding the major gridlines...as if the major gridline locations aren't proper multiples of the minor tick locations.

My setup is that I have a DataFrame called df which has a DatetimeIndex on the rows and a column called value which contains floats. I can provide an example of the df contents in a gist if necessary. A dozen or so lines of df are at the bottom of this post for reference.

Here's the code that produces the figure:

now = dt.datetime.now()  fig, axes = plt.subplots(2, 2, figsize=(15, 8), dpi=200) for i, d in enumerate([360, 30, 7, 1]):     ax = axes.flatten()[i]     earlycut = now - relativedelta(days=d)     data = df.loc[df.index>=earlycut, :]     ax.plot(data.index, data['value'])     ax.xaxis_date()      ax.get_xaxis().set_minor_locator(mpl.ticker.AutoMinorLocator())     ax.get_yaxis().set_minor_locator(mpl.ticker.AutoMinorLocator())      ax.grid(b=True, which='major', color='w', linewidth=1.5)     ax.grid(b=True, which='minor', color='w', linewidth=0.75) 

What is my best option here to get the x-axis labels to stop overlapping each other (in each of the four subplots)? Also, separately (but less urgently), what's up with the minor tick issue in the top-left subplot?

I am on Pandas 0.13.1, numpy 1.8.0, and matplotlib 1.4.x.

Here's a small snippet of df for reference:

                                    id scale  tempseries_id    value timestamp                                                            2014-11-02 14:45:10.302204+00:00  7564     F              1  68.0000 2014-11-02 14:25:13.532391+00:00  7563     F              1  68.5616 2014-11-02 14:15:12.102229+00:00  7562     F              1  68.9000 2014-11-02 14:05:13.252371+00:00  7561     F              1  69.0116 2014-11-02 13:55:11.792191+00:00  7560     F              1  68.7866 2014-11-02 13:45:10.782227+00:00  7559     F              1  68.6750 2014-11-02 13:35:10.972248+00:00  7558     F              1  68.4500 2014-11-02 13:25:10.362213+00:00  7557     F              1  68.1116 2014-11-02 13:15:10.822247+00:00  7556     F              1  68.2250 2014-11-02 13:05:10.102200+00:00  7555     F              1  68.5616 2014-11-02 12:55:10.292217+00:00  7554     F              1  69.0116 2014-11-02 12:45:10.382226+00:00  7553     F              1  69.3500 2014-11-02 12:35:10.642245+00:00  7552     F              1  69.2366 2014-11-02 12:25:12.642255+00:00  7551     F              1  69.1250 2014-11-02 12:15:11.122382+00:00  7550     F              1  68.7866 2014-11-02 12:05:11.332224+00:00  7549     F              1  68.5616 2014-11-02 11:55:11.662311+00:00  7548     F              1  68.2250 2014-11-02 11:45:11.122193+00:00  7547     F              1  68.4500 2014-11-02 11:35:11.162271+00:00  7546     F              1  68.7866 2014-11-02 11:25:12.102211+00:00  7545     F              1  69.2366 2014-11-02 11:15:10.422226+00:00  7544     F              1  69.4616 2014-11-02 11:05:11.412216+00:00  7543     F              1  69.3500 2014-11-02 10:55:10.772212+00:00  7542     F              1  69.1250 2014-11-02 10:45:11.332220+00:00  7541     F              1  68.7866 2014-11-02 10:35:11.332232+00:00  7540     F              1  68.5616 2014-11-02 10:25:11.202411+00:00  7539     F              1  68.2250 2014-11-02 10:15:11.932326+00:00  7538     F              1  68.5616 2014-11-02 10:05:10.922229+00:00  7537     F              1  68.9000 2014-11-02 09:55:11.602357+00:00  7536     F              1  69.3500 

Edit: Trying fig.autofmt_xdate(): I don't think this going to do the trick. This seems to use the same x-tick labels for both graphs on the left and also for both graphs on the right. Which is not correct given my data. Please see the problematic output below:

enter image description here

like image 882
8one6 Avatar asked Nov 02 '14 14:11

8one6


People also ask

How do you avoid overlapping X-axis labels in MatPlotLib?

Matplotlib x-axis label overlap In matplotlib, we have a method setp() that is used to set the rotation and alignment attributes of tick labels to avoid overlapping. To get ticklabels, we use the plt. setp() and get.

How do you prevent X-axis labels from overlapping?

0 A common problem in making plots, say a barplot or boxplot with a number of groups is that, names of the groups on x-axis label often overlap with each other. Till now, one of the solutions to avoid overlapping text x-axis is to swap x and y axis with coord_flip() and make a horizontal barplot or boxplot.

How do I stop MatPlotLib overlapping?

Use legend() method to avoid overlapping of labels and autopct. To display the figure, use show() method.

How do I stop subplots from overlapping in MatPlotLib?

Often you may use subplots to display multiple plots alongside each other in Matplotlib. Unfortunately, these subplots tend to overlap each other by default. The easiest way to resolve this issue is by using the Matplotlib tight_layout() function.


1 Answers

Ok, finally got it working. The trick was to use plt.setp to manually rotate the tick labels. Using fig.autofmt_xdate() did not work as it does some unexpected things when you have multiple subplots in your figure. Here's the working code with its output:

for i, d in enumerate([360, 30, 7, 1]):     ax = axes.flatten()[i]     earlycut = now - relativedelta(days=d)     data = df.loc[df.index>=earlycut, :]     ax.plot(data.index, data['value'])      ax.get_xaxis().set_minor_locator(mpl.ticker.AutoMinorLocator())     ax.get_yaxis().set_minor_locator(mpl.ticker.AutoMinorLocator())      ax.grid(b=True, which='major', color='w', linewidth=1.5)     ax.grid(b=True, which='minor', color='w', linewidth=0.75)      plt.setp(ax.get_xticklabels(), rotation=30, horizontalalignment='right')  fig.tight_layout() 

enter image description here

By the way, the comment earlier about some matplotlib things taking forever is very interesting here. I'm using a raspberry pi to act as a weather station at a remote location. It's collecting the data and serving the results via the web. And boy oh boy, it's really wheezing trying to put out these graphics.

like image 97
8one6 Avatar answered Sep 20 '22 11:09

8one6