【问题标题】:pandas : plot stacked barchart for row valuespandas:绘制行值的堆积条形图
【发布时间】:2018-06-26 11:44:11
【问题描述】:

我有以下数据框,我想为“关闭”/“打开”状态绘制堆积条形图。

             state  requests
created                          
2016-09-28    OPEN              1
2017-02-03    OPEN              1 
2017-06-15  CLOSED              1
2017-06-15    OPEN              1
2017-06-16  CLOSED              2
2017-08-23    OPEN              1
2017-10-25    OPEN              1
2018-01-19    OPEN              1
2018-03-01    OPEN              1
2018-03-05    OPEN              1
2018-06-12    OPEN              1
2018-06-15    OPEN              1

我尝试了以下(df_temp 是上述数据的数据框)

fig,ax = plt.subplots()
ax.set_ylabel('Requests')
df_closed = df_temp[df_temp['state'] == 'CLOSED']
df_open = df_temp[df_temp['state'] == 'OPEN']

b = ax.bar(x = df_open.index.get_level_values(0), height = df_open['requests'])
a = ax.bar(x = df_closed.index.get_level_values(0), height = df_closed['requests'],bottom = df_open['requests'])

但它给了我错误

ValueError: shape mismatch: objects cannot be broadcast to a single shape

编辑:

解决方案 Marco 建议可行,但如果有很多“状态”怎么办。例如,如果有 10 个不同的状态,那么我们可以通过循环或其他方式绘制它。我寻找了其他使用 pivot_table 和 unstack() 的问题,我不知道如何在这里使用它。

【问题讨论】:

  • 您可以在这里查看:matplotlib.org/examples/pylab_examples/bar_stacked.html。也就是说,首先你应该绘制两个中的一个(例如ax.bar(df_closed.index, df_closed.requests)),然后通过指定它应该从上面开始另一个(例如ax.bar(df_open.index, df_open.requests, bottom=df_closed.requests)。编辑:你应该首先确保它们具有相同的索引,例如@987654327 @,其中“...”是两组索引的并集。
  • @MarcoSpinaci,感谢您的回复,它有效,但如果“状态”列值未知怎么办。假设有 10 种不同的状态,那么我们有什么方法可以通过循环或其他方式来实现吗?
  • 是的,我可能会做一个 for 循环,类似于 for s in df.state.unique(),并在每一步更新一个“底部”系列,说明我们到目前为止添加了多少。

标签: python python-3.x pandas matplotlib


【解决方案1】:

由于您在堆叠条形图之前在一行中提到了 pandas pivot 功能 - you can transform your dataset with it

df_temp.pivot(columns = "state", values = "requests").plot(kind = "bar", stacked = True)

现在我们可以额外美化图形 - 标记 y 轴,旋转 x-tick 标签:

plt.ylabel("Requests")
plt.xticks(rotation = 45, ha = "right")
plt.tight_layout()
plt.show()

【讨论】:

  • 谢谢你,T 先生。效果很好,我发现数据透视表的语法有些混乱,这个对我有帮助。
  • 这绝对是实现范围的最干净的方法,比我的循环解决方案要好得多。
【解决方案2】:

我在这里发布一个正确的答案,因为它可能比保持评论更容易。这还包括另一种情况(在评论中询问),state 中可能存在任意的未知值集。

fig, ax = plt.subplots()
index = df_temp.index.unique()
cumsum = pd.Series(0, index=index)
for s in df.state.unique():
    new_vals = df_temp.loc[df.state == s, 'requests'].reindex(index).fillna(0)
    ax.bar(index, new_vals, bottom = cumsum)
    cumsum += new_vals
ax.set_ylabel('Requests')

这应该可以解决所有问题。在每个斧头中,我可能还会添加一个 label=s 并在最后添加一个 ax.legend() 以将每种结果颜色映射到一个状态。

【讨论】:

  • 谢谢你,马可。它适用于任意数量的状态。只是一个小错误,它应该是 ax.bar(index, new_vals, bottom = cumsum) 而不是 ax.bar(index, new_vals, cumsum),否则它只会为最后一个绘制图表。
猜你喜欢
  • 2016-05-24
  • 2018-11-26
  • 2012-09-17
  • 2021-12-27
  • 1970-01-01
  • 2018-09-28
相关资源
最近更新 更多