I am working on a plot where I want to show two groups on one axis and a third group as fill-value. The problem is, that when I plot it, the y-axis shows values in tuples:
data_dict = {'major_group': list(np.array([['A']*10, ['B']*10]).flat),
'minor_group': ['q ','r ','s ','t ']*5,
'legend_group':np.repeat(['d','e','f','g','h','i'],[7,3,1,5,1,3])}
(pd.DataFrame(data= data_dict)
.groupby(['major_group', 'minor_group','legend_group'], observed = True)
.size()
.unstack()
.plot(kind='barh', stacked=True))
Result:
However, I'm looking for something like this:
How can this be achieved? Is there some major and minor axis label that can be set?
This code will create horizontal stacked bars, grouped hierarchically in the y-axis label:
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from pandas import DataFrame
def create_data() -> DataFrame:
data_dict = {
'major_group': list(np.array([['A'] * 10, ['B'] * 10]).flat),
'minor_group': ['q', 'r', 's', 't'] * 5,
'legend_group': np.repeat(['d', 'e', 'f', 'g', 'h', 'i'], [7, 3, 1, 5, 1, 3])
}
return pd.DataFrame(data=data_dict).groupby(['major_group', 'minor_group', 'legend_group'], observed=True).size().unstack()
def plot_stacked_barh(df: DataFrame) -> None:
fig, axes = plt.subplots(nrows=2, ncols=1, sharex=True)
for i, major_group in enumerate(df.index.levels[0]):
ax = axes[i]
df.loc[major_group].plot(kind='barh', stacked=True, ax=ax, width=.8)
if i == 0:
handles, labels = ax.get_legend_handles_labels()
ax.legend_.remove()
ax.set_ylabel(major_group, weight='bold')
ax.xaxis.grid(visible=True, which='major', color='black', linestyle='--', alpha=.4)
ax.set_axisbelow(True)
fig.legend(handles, labels, title='Legend Group')
plt.tight_layout()
fig.subplots_adjust(hspace=0)
plt.show()
def main() -> None:
df = create_data()
print(df)
plot_stacked_barh(df)
if __name__ == "__main__":
main()
For a similar vertical equivalent, look here.