我有一个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
答案 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
与所需输出的两个区别是:
我希望这会有所帮助,或者至少会提供启发。
答案 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