Reputation: 2141
I've seen plenty of examples online of x-axis alignment for matplotlib Table with charts, but I can't figure out how to y-axis align my table. The following code produces the table pictured after it.
# For minimum viable example
dfx = [['ARS FX', 0.025346713729, 0.028238, 0.021889, 0.07701426, 0.0, 35, 39, '14.7%', 0.0, 0.07701426], ['BRL FX',1.83316130513e-05,0.025746,-0.072473, 0.143642325, 0.0, 40, 45, '12.3%', 0.0, 0.143642325], ['EUR FX', -0.301254060209, -0.300762, -0.290554, 0.0, -0.30127866, -60, -40, '5.2%', -0.30127866, 0.0], ['ZAR FX', 0.0515621470331, 0.053191, 0.044245, 0.07344438, 0.0, 10, 29, '14.1%', 0.0, 0.07344438], ['AR Eqity', 3.68762762118e-06, 0.0,0.0, 0.08817912, 0.0, 45, 45, '23.9%', 0.0, 0.08817912]]
dfx = pd.DataFrame(dfx)
dfx.columns = ['IdeaName', 'ModelWeight', 'Exposure_FXA', 'Exposure','Adj_Ubound', 'Adj_Lbound', 'lt_rob', 'st_rob', 'implied_vol', 'Lower Bound', 'Upper Bound']
# Plot
_, ax = plt.subplots()
dfx[['Lower Bound']].plot(kind='barh',ax=ax,color='red')
dfx[['Upper Bound']].plot(kind='barh',ax=ax,color='green')
plt.plot(dfx['ModelWeight'],range(len(dfx)), linestyle="", markersize=5, marker="o", color="#ff6600", label="ModelWeight", markeredgecolor="k")
plt.plot(dfx['Exposure'],range(len(dfx)), linestyle="", markersize=5, marker="o", color='lightblue', label="Exposure", markeredgecolor="k")
# Add a table at the bottom of the axes
columns = ['LT','ST','Vol']
the_table = ax.table(cellText=dfx[['lt_rob','st_rob','implied_vol']].values,
rowLabels=list(dfx['IdeaName']),
# rowColours=colors,
colWidths=[0.1 for x in columns],
colLabels=columns,
cellLoc='center',
loc=15)
the_table.auto_set_font_size(False)
the_table.set_fontsize(9)
the_table.scale(1, 1.05)
plt.subplots_adjust(left=0.4)
plt.yticks([])
plt.legend()
plt.show()
As you can see, despite me manually playing with the_table.scale()
to get it as close as possible, I can't get the rows aligned with my bars, since the column headers of the table are taking up the first row.
Any help appreciated. Thanks.
Upvotes: 0
Views: 1741
Reputation: 339200
The following would put the table into a bounding box that is one nth larger than the number of bars n. One then needs to make sure the margins within the axes are correct as well as the subplot parameter. The below only adjusts the vertical direction (the horizontal direction needs to be done by hand for longer labels).
import numpy as np
import matplotlib.pyplot as plt
data = np.random.randint(1,999,size=(10,4))
col = list("ABCD")
row = np.arange(1, len(data)+1)
n = len(data) # number of bars
barwidth = 0.8 # bar width
t = 0.05
b = 0.125
# Plot
fig, ax = plt.subplots()
fig.subplots_adjust(left=0.4, top=1-t-(1-t-b)/(n+1))
ax.margins(y=(1-barwidth)/2/n)
ax.barh(row, data[:,0], height=barwidth, label="bars", )
the_table = ax.table(cellText=data,
rowLabels=row,
colLabels=col,
cellLoc='center',
bbox=(-0.6, 0.0, 0.6, (n+1) / n))
the_table.auto_set_font_size(False)
the_table.set_fontsize(9)
fig.canvas.draw() # need to draw the figure twice
plt.yticks([])
plt.legend()
plt.show()
Upvotes: 3