【问题标题】:Bar chart with customised width in PythonPython中具有自定义宽度的条形图
【发布时间】:2020-04-27 17:27:48
【问题描述】:

我有这个数据框df,其中包含 -

Name       Team Name        Category       Challenge      Points            Time
 A            B               1              1ABC           50       2019-11-04 07:37:02        
 D            B               2              2ACE          150       2019-11-04 09:57:02
 X            P               4              4PQR          500       2019-11-05 08:45:02
 A            B               3              3PQR           10       2019-11-04 10:25:20
 N            P               4              4ABC          120       2019-11-05 08:35:00
 C            G               1              1ABC           50       2019-11-04 07:37:02
 D            B               4              4RST          200       2019-11-04 10:57:02

我有一个雄心勃勃的计划,将这个数据集可视化为自定义条形图,其中每个团队都有一个由不同宽度的块组成的建筑物(条形图)(取决于与该挑战相关的点),并且块的垂直顺序是取决于时间(第一个在底部)。简而言之,上述数据的图应大致如下所示 -

这里不同的颜色代表不同的类别。我知道如何按团队对数据进行分组,然后按 -

绘制每个团队的尝试次数
df.groupby(['Team Name'])['Challenge'].count().plot.bar()

但除此之外,我对如何更改条形宽度一无所知。有人可以帮忙吗? 或者,如果有人对如何使用任何传统情节进行可视化有更好的想法,我也很想听听您的意见。

谢谢!

【问题讨论】:

  • 您的预期输出是什么?各队总分?
  • 条的长度(Y 轴)是每个团队尝试的挑战总数(计数)。这些点将被可视化为建筑物上每个块的宽度。
  • 我认为您正在寻找堆叠条形图。

标签: python pandas matplotlib data-visualization


【解决方案1】:

这看起来像你想要的吗?

您可以通过matplotlib.patches 手动绘制“块”来完成此操作,它只需要一些额外的操作即可在算法上执行此操作。这是使用问题中提供的数据的完整示例

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
import numpy as np
import pandas as pd

t20 = [(31, 119, 180), (174, 199, 232), (255, 127, 14), (255, 187, 120)]
for i in range(len(t20)):    
    r, g, b = t20[i]    
    t20[i] = (r / 255., g / 255., b / 255.)

fig, ax = plt.subplots(1)
df['Time'] = pd.to_datetime(df['Time'])
df = df.sort_values('Time')
cat = df['Category'].unique()
cidx = dict(zip(cat, range(len(cat))))

mw = max(df['Points'])
names = list(df['Team Name'].unique())
nt = len(names)
h = 0.5
hs = [0]*3
for ii in range(len(df.index)):
    w = float(df['Points'].iloc[ii])/mw
    idx = names.index(df['Team Name'].iloc[ii])
    r = Rectangle((idx - w/2.0, hs[idx]), w, h, color=t20[cidx[df['Category'].iloc[ii]]])
    hs[idx] += 0.5
    ax.add_patch(r)
plt.xlim([-0.5, len(names)-0.5])
plt.ylim([0, max(hs)+3])
plt.xticks(range(len(names)), names)
plt.show()

如果您有兴趣,我使用了tableau 20 palette 中的前 4 种颜色。


编辑

你可以用线条添加图例

plt.legend(handles=[Patch(facecolor=t20[ii], label=cat[ii]) for ii in range(len(t20))])

只要包含从matplotlib.patches 额外导入的Patches,即

from matplotlib.patches import Rectangle, Patch

输出将是

【讨论】:

  • 是的! :) 谢谢!
  • 如何根据颜色(类别)向此地图添加图例?
  • 非常感谢!!这比我尝试的要容易得多.. :)
  • 你能告诉我如何为各个条形添加一些轮廓以及如何排序(例如,我希望它们按堆叠从最高到最低的顺序排列 B -> P -> G)?跨度>