Pandas groupby与Grouper速度

时间:2018-02-20 17:55:16

标签: python pandas dataframe

我想让每个医院每天获得平均Number of Records

|Hospital|Date|Number of Records
0|Hospital B|2018-02-12 16:07:54.183|5
1|Hospital B|2018-02-12 16:07:54.200|5
2|Hospital B|2018-02-12 16:07:54.220|2
3|Hospital B|2018-02-12 16:07:54.240|2
4|Hospital B|2018-02-12 16:07:54.253|1
5|Hospital B|2018-02-19 14:04:03.927|4
6|Hospital A|2017-12-18 00:00:00|9
7|Hospital A|2017-12-26 00:00:00|6
8|Hospital A|2018-02-05 14:12:49.587000|7

#df1 = pd.read_clipboard(sep='|')

这对于df1.groupby(['Hospital','Date']).sum().reset_index().groupby('Hospital').mean()来说很简单,但由于时间戳弄错了医院A的计算,这是不正确的。答案应该是9.5。

我可以通过截断日期来解决这个问题。

df1['Date'] = pd.to_datetime(df1['Date'])
df1['Date'] = df1['Date'].dt.date
df1.groupby(['Hospital', 'Date']).sum().reset_index().groupby('Hospital').mean()

Hospital A  7.333333
Hospital B  9.500000

我还试图用Grouper来解决这个问题,因为我不想“截断”我的日期以便以后分析,也不会创建额外的列来避免这种情况。令我惊讶的是,Grouper花了近2倍的时间。

df1.set_index('Date').groupby([pd.Grouper(freq='D'),'Hospital']).sum().\
                                dropna().groupby('Hospital').mean()

Hospital A  7.333333
Hospital B  9.500000
第一种方式为

100 loops, best of 3: 5.37 ms per loop,Grouper为100 loops, best of 3: 10.7 ms per loop

我在这里正确使用了Grouper吗?也许这需要很长时间,因为Grouper在我用drop_na()删除的索引中的日期之间创建了日期?

2 个答案:

答案 0 :(得分:2)

您也可以使用日期值而不覆盖您拥有的数据:

day = pd.to_datetime(df1['Date']).dt.date
df1.groupby(['Hospital', day]).sum().reset_index().groupby('Hospital').mean()

Hospital A  7.333333
Hospital B  9.500000

我猜测Grouper的性能问题就是你提到的,生成大量行只是为了以后丢弃它们。但是,使用to_datetime解析日期会产生必要的性能影响。您可以尝试避免解析并简单地切片:

day = df1['Date'].str.slice(0, 10)
df1.groupby(['Hospital', day]).sum().reset_index().groupby('Hospital').mean()

Hospital A  7.333333
Hospital B  9.500000

我的机器似乎稍微快一点,虽然我不知道大型数据集是否仍然如此。

答案 1 :(得分:2)

这样的东西
df.groupby(['Hospital', df.Date.str[:10]]).sum().mean(level=0)
Out[915]: 
                 Number of Records
Hospital                          
Hospital A  7.0           7.333333
Hospital B  7.5           9.500000