如何在水平堆叠的条形图中构建层次结构标签

时间:2018-08-03 09:09:43

标签: python pandas matplotlib axis-labels

我想要一个水平堆积的条形图,在y轴上带有层次结构标签。我搜索了一下,发现以下漂亮的示例和代码。

但这是用于垂直堆积的条形图的。我想将其应用于水平条形图,因此我只更改了import pandas as pd import numpy as np from matplotlib import pyplot as plt from itertools import groupby def test_table(): data_table = pd.DataFrame({'Room': ['Room A'] * 4 + ['Room B'] * 3, 'Shelf': ['Shelf 1'] * 2 + ['Shelf 2'] * 2 + ['Shelf 1'] * 2 + ['Shelf 2'], 'Staple':['Milk', 'Water', 'Sugar', 'Honey', 'Wheat', 'Corn', 'Chicken'], 'Quantity': [10, 20, 5, 6, 4, 7, 2,], 'Ordered': np.random.randint(0, 10, 7) }) data_table def add_line(ax, xpos, ypos): line = plt.Line2D([xpos, xpos], [ypos + .1, ypos], transform=ax.transAxes, color='black') line.set_clip_on(False) ax.add_line(line) def label_len(my_index,level): labels = my_index.get_level_values(level) return [(k, sum(1 for i in g)) for k,g in groupby(labels)] def label_group_bar_table(ax, df): ypos = -.1 scale = 1./df.index.size for level in range(df.index.nlevels)[::-1]: pos = 0 for label, rpos in label_len(df.index,level): lxpos = (pos + .5 * rpos)*scale ax.text(lxpos, ypos, label, ha='center', transform=ax.transAxes) add_line(ax, pos*scale, ypos) pos += rpos add_line(ax, pos*scale , ypos) ypos -= .1 df = test_table().groupby(['Room','Shelf','Staple']).sum() fig = plt.figure() ax = fig.add_subplot(111) df.plot(kind='bar',stacked=True,ax=fig.gca()) #Below 3 lines remove default labels labels = ['' for item in ax.get_xticklabels()] ax.set_xticklabels(labels) ax.set_xlabel('') label_group_bar_table(ax, df) fig.subplots_adjust(bottom=.1*df.index.nlevels) plt.show() ,但这是行不通的。

我设法通过在最后几行中将所有x更改为y来删除默认的ylabel。但是在定义的函数中将x更改为y并没有给我我想要的:层次结构标签仍在x轴上。

有人可以帮忙吗?谢谢。

P.S .:为了减少混乱,我将在this question的第二个答案中找到的原始代码发布了,而不是我尝试修改的代码

android:screenOrientation="sensorLandscape"

1 个答案:

答案 0 :(得分:1)

您可以执行以下操作。

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import pandas as pd
import numpy as np

data_table = pd.DataFrame({'Room': ['Room A'] * 4 + ['Room B'] * 3,
                           'Shelf': ['Shelf 1'] * 2 + ['Shelf 2'] * 2 + ['Shelf 1'] * 2 + ['Shelf 2'],
                           'Staple': ['Milk', 'Water', 'Sugar', 'Honey', 'Wheat', 'Corn', 'Chicken'],
                           'Quantity': [10, 20, 5, 6, 4, 7, 2, ],
                           'Ordered': np.random.randint(0, 10, 7)
                           })

arrays = [list(data_table['Room']), list(data_table['Shelf']), list(data_table['Staple'])]
data_table = data_table.groupby(['Room', 'Shelf', 'Staple']).sum()
index = pd.MultiIndex.from_tuples(list(zip(*arrays)))

df = pd.DataFrame(data_table[['Ordered', 'Quantity']], index=index).T

# plotting
fig = plt.figure()
height_ratios = [len(df[df.columns.levels[0][0]].columns), len(df[df.columns.levels[0][1]].columns)] #i.e. 4, 3
gs = gridspec.GridSpec(nrows=len(df.columns.levels[0]), ncols=1, height_ratios=height_ratios)

ax1 = fig.add_subplot(gs[0,0])
ax2 = fig.add_subplot(gs[1,0], sharex=ax1)
axes = [ax1, ax2]
for i, col in enumerate(df.columns.levels[0]):
    print(col)
    ax = axes[i]
    df[col].T.plot(ax=ax, stacked=True, kind='barh', width=.8)

    ax.legend_.remove()
    ax.set_ylabel(col, weight='bold')
    ax.xaxis.grid(b=True, which='major', color='black', linestyle='--', alpha=.4)
    ax.set_axisbelow(True)

    for tick in ax.get_xticklabels():
        tick.set_rotation(0)

ax.legend()
# make the ticklines invisible
ax.tick_params(axis=u'both', which=u'both', length=0)
plt.tight_layout()
# remove spacing in between
fig.subplots_adjust(wspace=0)  # space between plots

plt.show()

enter image description here

我改编了先前的答案of mine。请注意,层次结构分组显然在wishlist上,因此,这是在此处手动完成的。