1

I have a big multi-index dataframe, and I would like to build multiple horizontal stacked bar charts using for loop, but I couldn't get it right.

arrays = [['A', 'A', 'A','B', 'B', 'C', 'C'], 
['red', 'blue', 'blue','purple', 'red', 'black', 'white']]

df=pd.DataFrame(np.random.rand(7,4),
index=pd.MultiIndex.from_arrays(arrays, names=('letter', 'color')),
columns=["anna", "bill","david","diana"])

I have tried:

fig, axs = plt.subplots(nrows=1, ncols=3, figsize=(10,10))
for ax, letter in zip(axs, ["A","B","C"]):
    ax.set_title(letter)
for name in ["anna","bill","david","diana"]:
    ax.barh(df.loc[letter][name], width=0.3)

But this is not what I want.

What I hope to get is:

  • for each letter, there is a horizontal stacked bar chart

  • in each chart, colors are listed on y axis

  • values will be stacked by names (so names are the legend labels)

Since my dataframe is big, I hope to do this in a for loop. Can anyone help? Thanks.

Scott Boston
  • 147,308
  • 15
  • 139
  • 187
xiaoshir
  • 215
  • 4
  • 17

2 Answers2

1

Consider looping over the first index, letter, calling .loc which renders second index, color, as only index of looped data frame and then iteratively call pandas.DataFrame.plot:

fig, axs = plt.subplots(nrows=1, ncols=3, figsize=(10,10))

for ax, letter in zip(axs, ["A","B","C"]):
   df.loc[letter].plot(kind='barh', ax=ax, title=letter)
   ax.legend(loc='upper right')

plt.tight_layout()
plt.show()
plt.clf()
plt.close()

enter image description here

Parfait
  • 104,375
  • 17
  • 94
  • 125
1

IIUC, try the following:

grp = df.groupby(level=0)
fig, ax = plt.subplots(1, grp.ngroups, figsize=(10,10))
iax = iter(ax)

for n, g in grp:
    g.plot.barh(ax = next(iax), stacked = True, title = f'{n}')

plt.tight_layout()

Output: enter image description here

Scott Boston
  • 147,308
  • 15
  • 139
  • 187