如何计算两个日期之间的事件总数

时间:2019-11-04 05:37:16

标签: python pandas

我有一个DataFrame,需要在其中计算每个人两个日期之间的事件数。

在下面的DataFrame中,对于每个A型日期,我需要计算B型日期的数量,直到每个人的上一个A型日期为止。对于每个人,A和B型日期有多少没有限制。

我想避免for循环,因为它们很慢。

DataFrame

Person Date     Type 
1      01/01/19 A  
1      01/05/19 B 
1      02/01/19 A
1      03/01/19 A
2      01/01/19 A
2      01/07/19 B
2      01/25/19 B
2      02/01/19 A
2      02/05/19 B
2      04/01/19 A
3      03/01/19 A
3      04/01/19 A

所需的输出

Person Date   Count
1      2/1/19 1
1      3/1/19 0
2      2/2/19 2
2      4/1/19 1
3      4/1/19 0

2 个答案:

答案 0 :(得分:0)

您可以在没有for循环的情况下解决此问题。我的解决方案需要大量的预处理,最终结果并非完全像您期望的输出那样,而是非常接近(正确)的。为了清楚起见,我将其分为多个步骤-如果您想进行此类操作,则可以将其压缩为更少的内容。

import pandas as pd
import numpy as np

# Making dummy data
d = {"Person":[1,1,1,1,2,2,2,2,2,2,3,3],
     "Date":["01/01/19", "01/05/19", "02/01/19", "03/01/19", "01/01/19", "01/07/19", "01/25/19", 
             "02/01/19", "02/05/19", "04/01/19", "03/01/19", "04/01/19"],
     "Type":["A", "B", "A", "A", "A", "B", "B", "A", "B", "A", "A", "A"]}

df = pd.DataFrame(d)

df["isB"] = df["Type"] == "B"
df["step1"] = df["isB"].astype(int).diff().fillna(0)
df["step2"] = df["step1"]
df["step2"][df["isB"]] = 1
df["step3"] = (df["step2"] == -1).cumsum()
grouped = df.groupby(["Person", "step3"])

result = pd.DataFrame({"Date":grouped.last()["Date"], "Count":grouped["isB"].sum()})
result.index = result.index.droplevel(1)
result = result.reset_index()

print(result)

输出:

   Person      Date  Count
0       1  01/05/19    1.0
1       1  03/01/19    0.0
2       2  01/25/19    2.0
3       2  02/05/19    1.0
4       2  04/01/19    0.0
5       3  04/01/19    0.0

与所需输出的两个区别是:

  • 人员2有一个额外的条目。这是由于我的分组方式,导致人员2的最后一个“ A”条目是其自己的组,因此产生的计数为0。
  • 显示的日期是最后一个“ B”条目的日期,而不是下一个第一个“ A”条目的日期。不知道这是否值得解决,所以我没有。

我希望这会有所帮助,或者至少会提供启发。

答案 1 :(得分:0)

感谢molybdenum42的真知灼见。我不知道差异。这给了我一个关于在类型A过滤的索引上使用diff的想法。我找不到如何对索引本身执行此操作的功能,因此我将其复制到另一列。该数据框已经按“人”和“日期”排序,但是我将其包含在下面的代码中。

d = {"Person":[1,1,1,1,2,2,2,2,2,2,3,3],
     "Date":["01/01/19", "01/05/19", "02/01/19", "03/01/19", "01/01/19", "01/07/19", "01/25/19", 
             "02/01/19", "02/05/19", "04/01/19", "03/01/19", "04/01/19"],
     "Type":["A", "B", "A", "A", "A", "B", "B", "A", "B", "A", "A", "A"]}

df = pd.DataFrame(d)
df.Date = pd.to_datetime(df.Date)
df_sorted = df.sort_values(by=['Person', 'Date'])
df_sorted.reset_index(drop=True, inplace=True)
df_sorted['_index'] = df_sorted.index.values

group_a = df_sorted[df_sorted.Type == 'A'].groupby('Person')
df_sorted['Count'] = group_a['_index'].diff()-1
df_sorted[df_sorted.Count.notna()]

Person  Date    Type    _index  Count
1   02/01/19    A       2       1.0
1   03/01/19    A       3       0.0
2   02/01/19    A       7       2.0
2   04/01/19    A       9       1.0
3   04/01/19    A       11      0.0