假设我有以下数据框,并且我想计算出现次数" True"在过去14天内在同一类别中,我该怎么做?例如,以下数据框将生成一个值为0,1,1,0,2,0,1,0
的列Date Category has_egg
2017-01-01 Lunch True
2017-01-02 Lunch True
2017-01-02 Lunch False
2017-01-02 Dinner True
2017-01-12 Lunch False
2017-01-13 Breakfast False
2017-01-13 Dinner False
2017-02-04 Lunch True
我尝试使用group by但无法找出确切的命令
df.groupby("Category").has_egg.count_number_of_True(time_delta(-14d)) ?
答案 0 :(得分:2)
我认为只需合并resample
& rolling
groupby
pd.to_datetime
。 (请注意,下面的代码假定您的索引是正确的python / pandas日期时间。如果没有,您需要先将其转换为df.groupby('Category').resample('d').sum().fillna(0).\
groupby('Category').rolling(14,min_periods=1).sum()
。)
resample
rolling
行只是纠正了每个日期/类别可以包含多于或少于一行的事实。然后,您可以非常直接地使用Lunch Lunch 2017-01-01 1.0
2017-01-02 2.0
. . .
2017-01-14 2.0
2017-01-15 1.0
2017-01-16 0.0
。
这是输出的一部分:
df.groupby('Category').resample('w').sum().fillna(0).\
groupby('Category').rolling(2,min_periods=1).sum()
has_egg
Category Category Date
Breakfast Breakfast 2017-01-15 0.0
Dinner Dinner 2017-01-08 1.0
2017-01-15 1.0
Lunch Lunch 2017-01-01 1.0
2017-01-08 2.0
2017-01-15 1.0
2017-01-22 0.0
2017-01-29 0.0
2017-02-05 1.0
或者,为了简明起见,这是每周一次的样子:
monitorEvents()
我认为这种方式应该非常快,尽管不是内存效率,因为它将每个日期/类别组合的数据扩展到一行。如果内存是一个问题,你想要看一些替代方法(这可能会慢一点,也不那么优雅,所以除非你的数据相当大,否则我不会担心)。
另请注意:即使您的示例数据不包含该情况,如果您对唯一日期/类别有多个True值,我相信此代码也可以正常工作。如果您能够处理该示例数据,那么您可能希望编辑该示例数据。
答案 1 :(得分:2)
这可能不是一种有效的方法,但您可以做的是,迭代每一行并构建满足要求的mask
或其他dataframe
,并将它们计算为更新为新{ {1}}。
column
结果# converting to pandas datetime
df['Date'] = pd.to_datetime(df['Date']).dt.date
print(df)
是:
df
现在,遍历每一行并查找满足所有要求的那些并总结它们:
Date Category has_egg
0 2017-01-01 Lunch True
1 2017-01-02 Lunch True
2 2017-01-02 Lunch False
3 2017-01-02 Dinner True
4 2017-01-12 Lunch False
5 2017-01-13 Breakfast False
6 2017-01-13 Dinner False
7 2017-02-04 Lunch True
输出:
for index, row in df.iterrows():
mask = (df.Category == row.Category) & (df.Date > (row.Date - pd.Timedelta(days=14))) & (df.Date < row.Date) & (df.has_egg == True)
df.loc[index, 'values'] = sum(mask) # insert to the new column
print(df)