I've got a 3 level index. I'm holding two levels in control at all times and plotting data over the third. The plots look nice, but all three levels show as x-axis labels.
gb_zone_month_mean = df.groupby(by=["hemisphere", "climate_zone", "month"]).mean()
zones = [0, 1, 2, 3] # Climate zone (level 2 of index)
varis = variables[3:] # The 10 variables I care about.
idx = pd.IndexSlice
fig, ax = plt.subplots(4, 10, figsize=(20, 10))
for z_i in zones:
for i, v in zip(range(len(varis)), varis):
gb_zone_month_mean.loc[idx[1, z_i, :], v].plot(kind="bar", ax=ax[z_i][i])
plt.tight_layout()
plt.show()
As you can see, there is only one level of the multi-index that is varying in any given plot. That's the month.
How can I choose which level of the multi-index is shown in the x-axis labels?
CodePudding user response:
You can reset_index
with drop=True
before plot. Also, use groupby
would be much faster:
# sample data
df = pd.DataFrame(np.random.randint(0,10,(1000,4)), columns = ['a','b','c','d'])
# aggregation
groups = df.groupby(['a','b','c']).mean()
zones = [0,1,2,3]
varis = [3,4,5,6]
# create the axies, change to number you want
fig, axes = plt.subplots(4,10, figsize=(10,10))
# let say you want to plot on level `a`, `b`
# change to level name you want
# since `varis`, i.e. level `b` is selective, we query before groupby
for data,ax in zip(groups.query('b in @varis').groupby(['a','b']), axes.ravel()):
(zone, var), d = data
d.reset_index(level=['a','b'],drop=True)['d'].plot.bar(ax=ax)
Output:
Another option is seaborn's FacetGrid and barplot
import seaborn as sns
plot_data = groups.query('b in @varis').reset_index()
g = sns.FacetGrid(data=plot_data, row='b', col='a')
g.map(sns.barplot, 'c', 'd', order=plot_data['c'].unique())
You get: