1

I have an array of subplots, but whenever I try to reduce the tick density or even change the format, the values seem to change.

  1. Is there a distinction here between the 'tick' and its value? How would I match the correct value to the tick if so?

Here's a stand-alone plot that's right: France
enter image description here

Here's the (EDITED) code I'm trying:

import matplotlib as mpl
from matplotlib.ticker import FormatStrFormatter

f, axarr = plt.subplots(5,6,figsize=(30,30))
for i in range(0,6):
    for j in range(0,5):
        # there are only 26 entries in ser
        if (4*i+j) < 26:
            x = pp_gdp.loc[pp_gdp.index == ser.index[4*i+j],:].round(1)
            y = ser.loc[ser.index == ser.index[4*i+j],:].round(1)
            axarr[j,i].scatter(x,y)
            axarr[j,i].set_title(ser.index[4*i+j])
             xt = axarr[j,i].get_xticks()
        #axarr[j,i].set_xscale('linear')
        axarr[j,i].set_xticks([axarr[j,i].get_xticks()[0],int(len(axarr[j,i].get_xticks())/2), axarr[j,i].get_xticks()[-1]])
        axarr[j,i].set_xticklabels([x.values.min(),sorted(x.values)[0][int(len(xt)/2)],x.values.max()])
        yt = axarr[j,i].get_yticks()
        #axarr[j,i].set_yscale('linear')
        axarr[j,i].set_yticks([axarr[j,i].get_yticks()[0],int(len(axarr[j,i].get_yticks())/2), axarr[j,i].get_yticks()[-1]])
        axarr[j,i].set_yticklabels([y.values.min(),sorted(y.values)[0][int(len(yt)/2)],y.values.max()]);

Here's what I get if I comment out all the tick code, i.e. the default subplots: Default plot

As you can see, it's far too dense to read.

Here's what happens when I try nbins:

axarr[j,i].locator_params(tight=True, axis='y', nbins=10)
axarr[j,i].locator_params(tight=True, axis='x', nbins=5)

France nbins wrong
enter image description here

Again, the values are wrong on both axes.

Using the get_xticks and set_xticks as in the big code sample sort of works, but ruins the intuition of the plot. Also the scale is all wrong because of the way it keeps the 0.

Very linear plots stay linear, but the slope is exaggerated. Plots a little more complicated lose their shape altogether, as in: China now wrong

The chart on the rightis much harder to understand, just because the scale isn't playing nicely.

With my new

Thanks, Roy

Roy W.
  • 33
  • 7
  • I find it unclear what the problem is here. What's wrong with default labeling? It would choose nice ticks and ticklabels for you just automatically. – ImportanceOfBeingErnest Dec 06 '17 at 12:53
  • It's far too dense, and I'm not sure how to thin it out without returning the wrong values for the labels. I'll add a picture of what I'm getting as default. – Roy W. Dec 06 '17 at 14:18
  • You may use a `MaxNLocator` to get less ticks per axis. – ImportanceOfBeingErnest Dec 06 '17 at 14:20
  • Thank you, I just tried that, and I get the same issue as with the bins....the labels are wrong. – Roy W. Dec 06 '17 at 14:25
  • A label cannot be "wrong". You may explain better what you are tryingto achieve. But as there is also no [mcve] available, I doubt this issue is solvable. – ImportanceOfBeingErnest Dec 06 '17 at 14:30
  • Thanks for that link. You're right, I can't reproduce the error with simpler data/code. It works exactly as expected with simpler code. In my original example, the data for France for example, is between 60-80. But when I do any binning or MaxNLocating, it changes the labels to different values, leaving the shape and points the same. In France's case, it appears the data are between 57-60 now, when I know those values are wrong. With no binning, it also includes the 0 values, and makes the next tick start at 57, so it's like linear with a jump? Any suggestions? – Roy W. Dec 07 '17 at 00:06
  • Well, a [mcve] is a piece of code that allows to reproduce the error. So if your simpler code fails to reproduce the issue, you need to take more of what you do in your real program into account. In this case the "Divide and conquer" method seems necessary. Try to reproduce some part of the dataframe you work with by hardcoding the values. – ImportanceOfBeingErnest Dec 07 '17 at 00:24

2 Answers2

0

Based on bgamari's answer to this question, I'd suggest playing around with mpl.pyplot.locator_params(axis='x', nticks=4).

Peter Leimbigler
  • 10,775
  • 1
  • 23
  • 37
0

I don't know why, but it seems that pulling from 2 different data frames in the subplots was making it very unhappy.

Appending one array to the other and then creating subplots from it seemed to cure all my problems:

pp_gdp_1 = pp_gdp.loc[pp_gdp.index.isin(ser.index), :]
pp_gdp_s = pp_gdp_1.append(ser)
f, axarr = plt.subplots(7,4,figsize=(30,30))
for i in range(0,4):
    for j in range(0,7):
        # there are only 26 entries in ser
        if (7*i+j) < 26:
            x = pp_gdp_s.iloc[7*i+j].round(1)
            y = pp_gdp_s.iloc[(7*i+j)+len(ser)].round(1)
            axarr[j,i].scatter(x,y)
            axarr[j,i].set_title(ser.index[7*i+j])
            axarr[j,i].xaxis.set_major_locator(MaxNLocator(5))
            axarr[j,i].yaxis.set_major_locator(MaxNLocator(5))

This produces what I would get when I plotted them one at a time: Grid of good plots

Roy W.
  • 33
  • 7