我有一个数据框:
ColA ColB
0 A 1/2/2020
1 A 1/3/2020
2 A 1/4/2020
3 A 1/10/2020
4 B 1/3/2020
5 B 1/19/2020
6 C 1/2/2020
7 C 1/7/2020
8 D 1/8/2020
现在,我想在colA
中找出系列的名称,该系列在colB
中连续三天。
输出:
答案为A
,因为它在1/2/2020
中有1/3/2020
,1/4/2020
和colB
。
答案 0 :(得分:0)
一般方法如下:
# 1. To make sure the dates are sorted
df = df.sort_values(["ColA", "ColB"])
# 2. Standardize the dates by offseting them
df["ColB_std"] = df["ColB"] - pd.to_timedelta(range(df.shape[0]), 'day')
# 3. Counting each instance of ColA and standardized date
s = df.groupby(["ColA", "ColB_std"])["ColB_std"].count()
# 4. Getting elements from ColA that have at least 1 sequence of at least length 3
colA = s[ s >= 3 ].index.get_level_values(0).unique().values
# 5. Filtering the dataframe
df[ df["ColA"].isin(colA) ]
您希望ColA
连续3个日期。或者,您可以像想要ColA
那样date
,date + 1 day
和date + 2 days
的序列来思考它。通过按ColA和ColB (1)对数据框进行排序,我们知道在要检查的情况下,date + 1 day
将始终跟随date
,而date + 2 days
将是那个。
通过此操作,您可以通过删除n
天对应于其行的日期来标准化日期。因此,date
,date + 1 day
和date + 2 days
的序列变为date
,date
和date
(2)。
现在我们已经将日期列标准化了,我们只需要计算每对('ColA', 'ColB_std')
存在多少个元素(3),从ColA
中获得计数3个或更多(4),并过滤数据框(5)。
但是,这不支持重复的('ColA', 'ColB')
对,因为您首先需要这样做:
df2 = df.drop_duplicates(["ColA", "ColB"])
在步骤1、2、3和4中继续使用此df2
,最后在步骤5中过滤真实的df
。
以前,我回答过您也可以这样做:
# To make sure the dates are sorted
df = df.sort_values(["ColA", "ColB"])
# Calculating the difference between dates inside each group
s = df.groupby("ColA")["ColB"].diff().dt.days
# Filtering the dataframe
df[ ((s == 1) & (s.shift(1) == 1)).groupby(df["ColA"]).transform("any") ]
这个想法是,在s
中,差异始终在前一个日期和当前日期之间。但是,这不能确保有3个连续的日期,只有2个。通过将序列移位1,可以确保当前的日期和前一个日期是1 [{(s == 1) & (s.shift(1) == 1)
]。
此后,我只是groupby(df["ColA"])
,并使用transform("any")
检查组中是否有任何元素。