1

This code:

%matplotlib inline

import pandas as pd
import matplotlib.pyplot as plt

dc = pd.DataFrame({'A' : [1, 2, 3, 4],'B' : [4, 3, 2, 1],'C' : [3, 4, 2, 2]})

plt.plot(dc)
plt.legend(dc.columns)
plt.tight_layout()

dcsummary = pd.DataFrame([dc.mean(), dc.sum()],index=['Mean','Total'])

plt.table(cellText=dcsummary.values,colWidths = [0.25]*len(dc.columns),
        rowLabels=dcsummary.index,
        colLabels=dcsummary.columns,
        cellLoc = 'center', rowLoc = 'center',
        loc='top')
fig = plt.gcf()

#plt.show()

Will get a result looks like this (See/verify it here):

result1

However, if I disable the inline plotting and enable the plt.show() the result will look like this instead:

result2

I.e., the table will be cut-off from the graph if inline plotting is disabled. Since that's the only change I made, I think this is a bug with matplotlib, that it cannot produce consistent results.

Hope this can be fixed in future versions. Meanwhile, how can I fix it now (giving the fact that my real table is pulled from database using pd.read_sql, and its row count can vary from time to time)? PS, when giving the solution, please make sure it will still work when the graph title is added. Thanks.

UPDATE: More research revels that the problem has nothing to do with plt.tight_layout(). The following is one example I compiled together that doesn't have plt.tight_layout(), yet the table is not display properly as well when the graph inline plotting is disabled while inline plotting is still fine except for the title and table are colliding with each other:

import numpy as np
import pandas as pd

import matplotlib.pyplot as plt
plt.style.use('ggplot')

n=6
df = pd.DataFrame({
        'person':[x*16 for x in list('ABCDEF')],
        'score1':np.random.randn(n),
        'score2':np.random.randn(n),
        'score3':np.random.randn(n),
        'score4':np.random.randn(n),
        'score5':np.random.randn(n)
                   })
print(df)


plt.close('all')  # close all open figures

fig, ax = plt.subplots()

# X: pd.options.display.mpl_style = 'default' # cause system freeze
df.set_index(['person']).plot(kind='barh', ax = ax, width=0.85, fontsize=8)
ax.invert_yaxis()

plt.title("Matplotlib table plotting")

#plt.tight_layout()

# Add a table
plt.table(cellText=df.values,colWidths = [0.25]*len(df.columns),
        rowLabels=df.index,
        colLabels=df.columns,
        cellLoc = 'center', rowLoc = 'center',
        loc='top')

plt.show()

The question remains, how can I fix the above graphs?

Thanks

xpt
  • 20,363
  • 37
  • 127
  • 216
  • It works fine without inline plotting as long as you get rid of the tight layout. You can set `bbox_inches='tight'` to `plt.savefig` to eliminate extra whitespace without truncating your plot. – Alex Huszagh Dec 17 '15 at 19:58
  • I do need that `plt.tight_layout()` though (see http://stackoverflow.com/questions/34300060/pandas-bar-chart-settings-customization/34301061), in order not to eliminate extra whitespace, but to gain extra whitespace for my y-labels. Can I have both? Thx. – xpt Dec 17 '15 at 20:05
  • Also, this is likely a bug but tables are not currently considered in calculating the space for a tight layout, and as this is an experimental feature, I'm afraid the answer is "no": http://matplotlib.org/users/tight_layout_guide.html A direct quote is as follows: "tight_layout automatically adjusts subplot params so that the subplot(s) fits in to the figure area. This is an experimental feature and may not work for some cases. It only checks the extents of ticklabels, axis labels, and titles." – Alex Huszagh Dec 17 '15 at 20:06

0 Answers0