我有一个数据集(测试),其中包含几个项目的信息,其中包含 Typ、Beginning 和 End:
ID Name Type Start End
1 la A 2000 2003
2 le B 2001 2002
3 li A 2001 2004
4 lo B 2002 2003
5 lu A 2001 2002
我想绘制每年按类型堆积的正在运行的项目。
我能够生成项目开始或结束的图表,这样做:
test[(test['Start']>=2000) & (test['End']<=2004)].groupby(['Start','Type']).size().unstack(fill_value=0).plot(kind='bar', legend=False, stacked=True)
但是,正如您所看到的,项目的不同持续时间使得查看正在运行的项目变得非常重要。 所以我希望我有四个小节 [2000、2001、2002、2003、2004]。 2001 年的 Bar 高度应为 4,即 3 倍 A 型(la、li、lu)和 1 倍 B 型(le)。本例中的 case lo 不属于酒吧的一部分,因为它始于 2002 年。
(简短/优雅的)解决方案是什么? 我缺少哪些关键字而无法找到这样的解决方案?
最佳答案
您可以使用 range
和 join
创建新系列原始df
:
s = (df.apply(lambda x: pd.Series(range(x['Start'], x['End'] + 1)), 1)
.stack()
.rename('year')
.reset_index(level=1, drop=True)
.astype(int))
df = df.join(s)
print (df)
ID Name Type Start End year
0 1 la A 2000 2003 2000
0 1 la A 2000 2003 2001
0 1 la A 2000 2003 2002
0 1 la A 2000 2003 2003
1 2 le B 2001 2002 2001
1 2 le B 2001 2002 2002
2 3 li A 2001 2004 2001
2 3 li A 2001 2004 2002
2 3 li A 2001 2004 2003
2 3 li A 2001 2004 2004
3 4 lo B 2002 2003 2002
3 4 lo B 2002 2003 2003
4 5 lu A 2001 2002 2001
4 5 lu A 2001 2002 2002
df.groupby(['year','Type']).size().unstack(fill_value=0)
.plot(kind='bar', legend=False, stacked=True)
对于新的DataFrame
,也可以使用列表理解:
d = [(x['Type'], y) for i, x in df.T.items() for y in range(x['Start'], x['End'] + 1)]
print (d)
[('A', 2000), ('A', 2001), ('A', 2002), ('A', 2003), ('B', 2001),
('B', 2002), ('A', 2001), ('A', 2002), ('A', 2003), ('A', 2004),
('B', 2002), ('B', 2003), ('A', 2001), ('A', 2002)]
与循环版本相同的内容:
d = []
for i, x in df.T.items():
a = range(x['Start'], x['End'] + 1)
for y in a:
d.append((x['Type'], y))
然后是DataFrame
构造函数:
df = pd.DataFrame(d, columns=['Type','year'])
print (df)
Type year
0 A 2000
1 A 2001
2 A 2002
3 A 2003
4 B 2001
5 B 2002
6 A 2001
7 A 2002
8 A 2003
9 A 2004
10 B 2002
11 B 2003
12 A 2001
13 A 2002
关于python - Pandas:绘制正在运行的项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47813586/