我有一个棘手的问题无法解决。我有数百万行,需要标记当前行和上一行之间的重叠日期。这些行按“KEY”分组,在该分组中,我需要标记具有“Date1”的行,该行与上一行的“Date2”重叠。
重叠行是指第二行的 Date1 小于前一行的 Date2,并且第二行的 Date1 大于或等于前一行的 Date1。
简单地说:如果第二行的 date1 介于前一行的 date1 和 date2 之间,则将这两行标记为重叠行。仅供引用,在任何给定行上,Date1 永远不会大于 Date2。
上一行日期 1 <= 第二行日期 1 < 上一行日期 2
我不明白的困难部分是这一步需要按顺序执行。也就是说,如果该分组中的第二行被标记,则该组中的下一行(第 3 行)将与第一行进行比较(在这种情况下,第一行也将被标记为与第 2 行重叠)。
这是一个数据集:
df = pd.DataFrame({'KEY': ['100000003', '100000009', '100000009', '100000009', '100000009','100000034','100000034', '100000034'],
'Date1': [20120506, 20120506, 20120507,20120608,20120620,20120206,20120304,20120405],
'Date2': [20120528, 20120610, 20120615,20120629,20120621,20120305,20120506,20120506]})
df['Date1'] = pd.to_datetime(df["Date1"], format='%Y%m%d')
df['Date2'] = pd.to_datetime(df["Date2"], format='%Y%m%d')
df.sort_values(by=['KEY','Date1','Date2'], inplace=True)
df[['KEY','Date1','Date2']]
KEY Date1 Date2
0 100000003 2012-05-06 2012-05-28
1 100000009 2012-05-06 2012-06-10
2 100000009 2012-05-07 2012-06-15
3 100000009 2012-06-08 2012-06-29
4 100000009 2012-06-20 2012-06-21
5 100000034 2012-02-06 2012-03-05
6 100000034 2012-03-04 2012-05-06
7 100000034 2012-04-05 2012-05-06
由于有数百万行,并且每个组的大小各不相同,因此我编写了一个 for 循环,它只会迭代最大数量的 groupby KEY。
for item in range(df.groupby('KEY')['KEY'].count().max()):
df['PrevDate1'] = df.groupby('KEY')['Date1'].shift(1)
df['PrevDate2'] = df.groupby('KEY')['Date2'].shift(1)
df['Overlapping_Hospitalizations'] = np.where(df['Date1'].between(df['PrevDate1'],df['PrevDate2']),'Y','N')
print("DONE")
df
这适用于之前的每个 KEY,但我还需要它与导致该分组重叠的初始 KEY 进行比较。
预期结果:
KEY Date1 Date2 OverlappingFlag
0 100000003 2012-05-06 2012-05-28 N
1 100000009 2012-05-06 2012-06-10 Y
2 100000009 2012-05-07 2012-06-15 Y
3 100000009 2012-06-08 2012-06-29 Y
4 100000009 2012-06-20 2012-06-21 Y
5 100000034 2012-02-06 2012-03-05 Y
6 100000034 2012-03-04 2012-05-06 Y
7 100000034 2012-04-05 2012-05-06 Y
编辑:两个重叠的行都需要标记。查看预期结果。
最终答案:
for item in range(df.groupby('KEY')['KEY'].count().max()):
df['overlap'] = (((df['KEY'] == df['KEY'].shift()) & \
(df['Date1'] >= df['Date1'].shift(1)) & \
(df['Date1'] < df['Date2'].shift(1))) | \
((df['KEY'] == df['KEY'].shift(-1)) & \
(df['Date1'].shift(-1) >= df['Date1']) & \
(df['Date1'].shift(-1) < df['Date2'])))
最佳答案
看起来问题中的预期结果不符合定义:
The rows are grouped by 'KEY' and within this grouping I need to flag rows that have 'Date1' which overlaps with the 'Date2' of the previous row.
KEY Date1 Date2 OverlappingFlag
0 100000003 2012-05-06 2012-05-28 N
1 100000009 2012-05-06 2012-06-10 Y # probably not
2 100000009 2012-05-07 2012-06-15 Y
3 100000009 2012-06-08 2012-06-29 Y
4 100000009 2012-06-20 2012-06-21 Y
5 100000034 2012-02-06 2012-03-05 Y # probably not
6 100000034 2012-03-04 2012-05-06 Y
7 100000034 2012-04-05 2012-05-06 Y
本例中 @Evan 代码的扩展:
import pandas as pd
import numpy as np
df = pd.DataFrame({'KEY': ['100000003', '100000009', '100000009', '100000009', '100000009','100000034','100000034', '100000034'],
'Date1': [20120506, 20120506, 20120507,20120608,20120620,20120206,20120304,20120405],
'Date2': [20120528, 20120610, 20120615,20120629,20120621,20120305,20120506,20120506]})
df['Date1'] = pd.to_datetime(df["Date1"], format='%Y%m%d')
df['Date2'] = pd.to_datetime(df["Date2"], format='%Y%m%d')
df.sort_values(by=['KEY','Date1','Date2'], inplace=True)
# if KEY is already an index, df = df.reset_index()
# df.set_index('KEY', inplace = True)
# this is really the only part changed
df['overlap'] = ((df.KEY == df.KEY.shift()) & \
(df.Date1 < df.Date2.shift())) | \
((df.KEY == df.KEY.shift(-1)) & \
(df.Date2 < df.Date1.shift(-1)))
df.set_index('KEY', inplace = True)
关于python - Pandas:标记重叠日期,但如果满足条件则排除某些行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48671669/