Matplotlib fill in missing Tic labels

I have a list of Pandas dataframes (example):

df1 = pd.DataFrame({'Number':[-9,-8,0,1,2,3], 'A':[3,6,4,1,7,19], 'B':[2,4,4,0,7,1]})
df1.set_index('Number',inplace=True)

df2 = pd.DataFrame({'Number':[0,5,6,7,8,9], 'A':[8,7,3,5,2,15], 'B':[1,7,1,1,1,3]})
df2.set_index('Number',inplace=True)

df_list = [df1, df2] #In reality there are more than two in the list

      

and I would try to plot them using Matplotlib:

nrow = 2
ncol = 2
fig, axs = plt.subplots(nrow,ncol)

for i in range(nrow*ncol):
    #Convert 1D to 2D
    row = i / ncol
    col = i % ncol
    if i >= len(df_list):
        axs[row,col].axis('off')
    else:
        df_list[i]['A'].plot(kind='bar',
              ax=axs[row,col],
              ylim=(0,20),
              xlim=(-10,10),
              figsize=(20,15),
              color=('green'),
              legend=False,
              )
        df_list[i]['B'].plot(kind='bar',
              ax=axs[row,col],
              ylim=(0,20),
              xlim=(-10,10),
              figsize=(20,15),
              color=('yellow'),
              legend=False,
              ) 

      

The resulting plots look like this: enter image description here Everything looks fine except for the xtic labels, which I believe will be spaced according to its value (i.e. "-9" should not be in the middle of the plot or "0" should not be near with "5", etc.). In fact, since my x-range is roughly (-10,10), I want the entire full range to be displayed along the x-axis, and for the color stripes accordingly by their "number". One possible solution I came across was to fill in the missing values ​​from (-10,10) using Pandas, but I guess there is a better / more obvious way to handle this. I just couldn't figure out this solution.

Update:

Thanks to Ajean's (and JD Long's) answers below, I am now using this Matplotlib code:

df_list = [df1, df2]

nrow = 2
ncol = 2
fig, axs = plt.subplots(nrow,ncol,figsize=(20,15))

for i in range(nrow*ncol):
    #Convert 1D to 2D
    row = i / ncol
    col = i % ncol
    if i >= len(df_list):
        axs[row,col].axis('off')
    else:
        axs[row,col].bar(np.array(df_list[i].index)-0.5, df_list[i]['A'], width=1, color='green')
        axs[row,col].bar(np.array(df_list[i].index)-0.5, df_list[i]['B'], width=1, color='yellow')
        axs[row,col].set_xlim([-10,10])
        axs[row,col].set_ylim([0,20])
        axs[row,col].xaxis.set_ticks(np.arange(-10, 11, 1))

      

which produces this (desired) result:

enter image description here

Note: The width of each bar is set to 1.0, and they are shifted by -0.5 to center each baht over the tic marks.

+3


source to share


2 answers


It looks like Pandas has not yet provided the functionality of its histogram wrapper to explicitly place bar positions. A value of 0.14.0 "What's New" means "the coordinates of the lineplots are now at integer values ​​(0.0, 1.0, 2.0 ...)" and nothing changed until 0.15.1 as far as I can tell.

So I would skip the Pandas interface (which you most definitely use) for this and use Matplotlib directly.

nrow = 1
ncol = 2
fig, axs = plt.subplots(nrow,ncol)

for i in range(nrow*ncol):
    if i >= len(df_list):
        axs[i].axis('off')
    else:
        # You could theoretically turn this into a loop over your columns
        # with appropriate widths and offsets
        axs[i].bar(df_list[i].index-0.4, df_list[i]['A'], width=0.4, color='green')
        axs[i].bar(df_list[i].index, df_list[i]['B'], width=0.4, color='yellow')

      



The above code is modified with your specific DataFrame list, which creates the graph below (I've excluded the additional axes for simplicity).

bar chart at exact locations

NOTE . The operation df_list[i].index-0.4

under Pandas 0.14.0 throws an error, which is a bug that was fixed in 0.15.1. You can work around this by converting the index to a regular numpy array first, or by simply updating pandas.

+1


source


You have asked a very good question. Thanks for having a reproducible example that makes it easier to help him.

The problem is that Pandas chart code accepts categorical data on the x axis. Obviously, you don't have categorical data. However, there is no way to tell Matplotlib that through the Pandas interface (which I know).



The most obvious solution to me is the one you present for adding values. I would do it, perhaps via a connection. I would join an existing fileframe with an index that had all the values ​​I wanted on the x-axis and join the option how='outer'

.

0


source







All Articles