使用分组的 Pandas 数据框绘制堆叠图

3

我有一个数据框,如下所示。首先,我想要每个日期中每种状态的数量。例如,2017年11月2日'COMPLETED'的数量为2。我想绘制这样的堆积图。

                   status              start_time                end_time  \
0             COMPLETED 2017-11-01 19:58:54.726 2017-11-01 20:01:05.414   
1             COMPLETED 2017-11-02 19:43:04.000 2017-11-02 19:47:54.877   
2     ABANDONED_BY_USER 2017-11-03 23:36:19.059 2017-11-03 23:36:41.045   
3  ABANDONED_BY_TIMEOUT 2017-10-31 17:02:38.689 2017-10-31 17:12:38.844   
4             COMPLETED 2017-11-02 19:35:33.192 2017-11-02 19:42:51.074   

以下是数据框的csv文件:

status,start_time,end_time
COMPLETED,2017-11-01 19:58:54.726,2017-11-01 20:01:05.414
COMPLETED,2017-11-02 19:43:04.000,2017-11-02 19:47:54.877
ABANDONED_BY_USER,2017-11-03 23:36:19.059,2017-11-03 23:36:41.045
ABANDONED_BY_TIMEOUT,2017-10-31 17:02:38.689,2017-10-31 17:12:38.844
COMPLETED,2017-11-02 19:35:33.192,2017-11-02 19:42:51.074
ABANDONED_BY_TIMEOUT,2017-11-02 19:35:33.192,2017-11-02 19:42:51.074

为了实现这个目标:
df_['status'].astype('category')
df_ = df_.set_index('start_time')
grouped = df_.groupby('status')
color = {'COMPLETED':'green','ABANDONED_BY_TIMEOUT':'blue',"MISSED":'red',"ABANDONED_BY_USER":'yellow'}

for key_, group in grouped:
   print(key_)
   df_ = group.groupby(lambda x: x.date).count()
   print(df_)
   df_['status'].plot(label=key_,kind='bar',stacked=True,\
   color=color[key_],rot=90)
plt.show()

以下代码的输出结果为:
ABANDONED_BY_TIMEOUT
            status  end_time  
2017-10-31       1         1       
ABANDONED_BY_USER
            status  end_time  
2017-11-03       1         1            
COMPLETED
            status  end_time  
2017-11-01       1         1             
2017-11-02       2         2 

来自上述代码的图形

可以看到这里的问题是只考虑了最后两个日期“2017-11-01”和“2017-11-02”,而没有考虑所有类别中的所有日期。 我该如何解决这个问题?欢迎提供全新的层叠图方法。谢谢。


请将您的完整数据框以csv格式发布在您的问题中。 - Nihal
这是您需要的,已使用 CSV 进行编辑。 - gokyori
3个回答

2
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

df_ = pd.read_csv('sam.csv')
df_['date'] = pd.to_datetime(df_['start_time']).dt.date
df_ = df_.set_index('start_time')


grouped = pd.DataFrame(df_.groupby(['date', 'status']).size().reset_index(name="count")).pivot(columns='status', index='date', values='count')
print(grouped)
sns.set()

grouped.plot(kind='bar', stacked=True)

# g = grouped.plot(x='date', kind='bar', stacked=True)
plt.show()

输出:

enter image description here


2
尝试使用 pandas.crosstab 重构df_
color = ['blue', 'yellow', 'green', 'red']
df_xtab = pd.crosstab(df_.start_time.dt.date, df_.status)

这个DataFrame将会长成这样:
status      ABANDONED_BY_TIMEOUT  ABANDONED_BY_USER  COMPLETED
start_time                                                    
2017-10-31                     1                  0          0
2017-11-01                     0                  0          1
2017-11-02                     1                  0          2
2017-11-03                     0                  1          0

最初的回答,并且将更容易绘制。
df_xtab.plot(kind='bar',stacked=True, color=color, rot=90)

enter image description here


1

使用 Seaborn 库 barplot 并结合它的色调

代码:

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

df_ = pd.read_csv('sam.csv')
df_['date'] = pd.to_datetime(df_['start_time']).dt.date
df_ = df_.set_index('start_time')

print(df_)

grouped = pd.DataFrame(df_.groupby(['date', 'status']).size().reset_index(name="count"))
print(grouped)

g = sns.barplot(x='date', y='count', hue='status', data=grouped)
plt.show()

输出: 在此输入图像描述


数据:

status,start_time,end_time
COMPLETED,2017-11-01 19:58:54.726,2017-11-01 20:01:05.414
COMPLETED,2017-11-02 19:43:04.000,2017-11-02 19:47:54.877
ABANDONED_BY_USER,2017-11-03 23:36:19.059,2017-11-03 23:36:41.045
ABANDONED_BY_TIMEOUT,2017-10-31 17:02:38.689,2017-10-31 17:12:38.844
COMPLETED,2017-11-02 19:35:33.192,2017-11-02 19:42:51.074
ABANDONED_BY_TIMEOUT,2017-11-02 19:35:33.192,2017-11-02 19:42:51.074

enter image description here


谢谢你的回答,我稍微改变了数据,以便更容易地可视化堆叠条形图。我不认为你的答案对此有帮助。有什么解决方案吗? - gokyori
它仍然在执行它的工作。 - Nihal
什么问题?我不明白。 - Nihal
对于日期2017-11-02,我想要一个堆积条形图而不是一组垂直条。 - gokyori

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接