我有一个数据框,如下所示。 这是检查员提出问题的数据。
Iss_id Ins_ID XY Duplicate Raised_Date Type
1 1 (2,5) Yes 2019-10-07 10:27:50 A
2 1 (2,5) Yes 2019-10-07 10:27:50 A
3 2 (2,5) No 2019-10-07 10:27:50 A
4 2 (3,5) No 2019-10-07 10:29:50 A
5 2 (2,5) No 2019-10-07 10:29:50 A
6 2 (2,5) No 2019-10-07 10:29:50 A
7 3 (2,5) No 2019-10-07 11:27:50 A
8 2 (2,5) No 2019-10-07 11:27:50 B
9 3 (2,5) No 2019-10-07 10:27:50 C
10 2 (2,5) Yes 2019-10-07 10:27:50 A
从上面我想根据条件找出实际重复项
条件1:在重复编号中,匹配所有其他行。也就是说,同一检查人员在相同的XY位置同时提出相同的问题类型。
预期的输出1:
Iss_id Ins_ID XY Duplicate Raised_Date Type
5 2 (2,5) No 2019-10-07 10:29:50 A
6 2 (2,5) No 2019-10-07 10:29:50 A
条件2:在重复的编号中,同一检查员在5分钟内以相同的XY提出相同的问题类型。
预期的输出2:
Iss_id Ins_ID XY Duplicate Raised_Date Type
3 2 (2,5) No 2019-10-07 10:27:50 A
5 2 (2,5) No 2019-10-07 10:29:50 A
6 2 (2,5) No 2019-10-07 10:29:50 A
条件3:在重复的编号中,在相同的XY处,在120分钟内键入相同的问题。 (检查员可以相同,也可以不同)。
预期的输出3:
Iss_id Ins_ID XY Duplicate Raised_Date Type
3 2 (2,5) No 2019-10-07 10:27:50 A
5 2 (2,5) No 2019-10-07 10:29:50 A
6 2 (2,5) No 2019-10-07 10:29:50 A
7 3 (2,5) No 2019-10-07 11:27:50 A
答案 0 :(得分:3)
第一部分答案是仅匹配重复的No
列(如果不存在Yes
行:
df['Raised_Date'] = pd.to_datetime(df['Raised_Date'])
df1 = df[df.drop(['Duplicate','Iss_id'], 1).duplicated(keep=False)]
mask = (df1.assign(Duplicate = df1['Duplicate'].eq('No'))
.groupby(df1.columns.difference(['Duplicate','Iss_id']).tolist())['Duplicate']
.transform('all'))
df1 = df1[mask]
print (df1)
Iss_id Ins_ID XY Duplicate Raised_Date Type
4 5 2 (2,5) No 2019-10-07 10:29:50 A
5 6 2 (2,5) No 2019-10-07 10:29:50 A
对于接下来的2个解决方案,使用merge_asof
函数和可能的公差参数,并通过参数by
检查同一列:
df21 = df[df['Duplicate'].eq('No')].sort_values('Raised_Date').copy()
df22 = df1.drop_duplicates().sort_values('Raised_Date').copy()
#print (df21)
#print (df22)
df2 = (pd.merge_asof(df21, df22,
on='Raised_Date',
by=['Ins_ID','XY','Type'],
tolerance=pd.Timedelta(5 * 60, unit='s'),
direction='forward',
suffixes=('','_'))
.dropna(subset=['Duplicate_'])
.drop(['Duplicate_','Iss_id_'], axis=1))
print (df2)
Iss_id Ins_ID XY Duplicate Raised_Date Type
0 3 2 (2,5) No 2019-10-07 10:27:50 A
3 5 2 (2,5) No 2019-10-07 10:29:50 A
4 6 2 (2,5) No 2019-10-07 10:29:50 A
类似的解决方案,只需要direction='forward'
和direction='backward'
(默认值,因此省略),合并列并过滤不丢失的行:
df31 = (pd.merge_asof(df21, df22,
on='Raised_Date',
by=['XY','Type'],
tolerance=pd.Timedelta(120 * 60, unit='s'),
direction='forward',
suffixes=('','_'))
)
df32 = (pd.merge_asof(df21, df22,
on='Raised_Date',
by=['XY','Type'],
tolerance=pd.Timedelta(120 * 60, unit='s'),
suffixes=('','_'))
)
df3 = df21[df31['Duplicate_'].fillna(df32['Duplicate_']).notna().to_numpy()]
print (df3)
Iss_id Ins_ID XY Duplicate Raised_Date Type
2 3 2 (2,5) No 2019-10-07 10:27:50 A
4 5 2 (2,5) No 2019-10-07 10:29:50 A
5 6 2 (2,5) No 2019-10-07 10:29:50 A
6 7 3 (2,5) No 2019-10-07 11:27:50 A