例如,我有一个Pandas 数据帧
df_dupl = pd.DataFrame({
'EVENT_TIME': ['00:01', '00:01', '00:01', '00:03', '00:03', '00:03', '00:06', '00:06', '00:06', '00:08', '00:08', '00:10', '00:10', '00:11', '00:11', '00:13', '00:13', '00:13'],
'UNIQUE_ID': [123, 123, 123, 125, 125, 125, 123, 123, 123, 127, 127, 123, 123, 123, 123, 123, 123, 123],
'Value1': ['A', 'B', 'A', 'A', 'B', 'A', 'A', 'B', 'A', 'A', 'B', 'A', 'B', 'C', 'B', 'A', 'B', 'A'],
'Value2': [0.3, 0.2, 0.2, 0.1, 1.3, 0.2, 0.3, 0.2, 0.2, 0.1, 1.3, 0.3, 0.2, 0.3, 0.2, 0.3, 0.2, 0.2]
})
我想删除与具有相同UNIQUE_ID的前一行(按EVENT_TIME)具有相同值的行的序列. 对于该示例,结果应如下所示:
df = pd.DataFrame({
'EVENT_TIME': ['00:01', '00:01', '00:01', '00:03', '00:03', '00:03', '00:08', '00:08', '00:10', '00:10', '00:11', '00:11', '00:13', '00:13', '00:13'],
'UNIQUE_ID': [123, 123, 123, 125, 125, 125, 127, 127, 123, 123, 123, 123, 123, 123, 123],
'Value1': ['A', 'B', 'A', 'A', 'B', 'A', 'A', 'B', 'A', 'B', 'C', 'B', 'A', 'B', 'A'],
'Value2': [0.3, 0.2, 0.2, 0.1, 1.3, 0.2, 0.1, 1.3, 0.3, 0.2, 0.3, 0.2, 0.3, 0.2, 0.2]
}).
应该删除时间为00:06的行,因为先前具有UNIQUE_ID 123(时间00:01)的子数据帧是相同的. 另一方面,应该保留时间为00:13的行-它们也与时间为00:01的行相同,但有其他行的UNIQUE_ID介于123之间. 关键是我想要比较整个子数据帧,而不是单行.
我可以通过使用以下功能达到预期的效果,但速度很慢.
def del_dupl_gr(df):
out = []
for x in df['UNIQUE_ID'].unique():
prev_df = pd.DataFrame()
for y in df[df['UNIQUE_ID'] == x]['EVENT_TIME'].unique():
test_df = df[(df['UNIQUE_ID'] == x) & (df['EVENT_TIME'] == y)]
if not test_df.iloc[:, 2:].reset_index(drop=True).equals(prev_df.iloc[:, 2:].reset_index(drop=True)):
out.append(test_df)
prev_df = test_df
return pd.concat(out).sort_index().reset_index(drop=True)
真正的数据帧相当大(超过百万行),这个循环需要很长时间.我相信肯定有合适的(或者至少是更快的)方法来做到这一点.
Results个
感谢所有提交的答案.我比较了他们的速度.在某些情况下,我略微编辑了这些方法,以产生完全相同的结果.因此,在所有SORT_VALUES方法中,我添加了KIND=‘STRATE’以确保保持顺序,并在末尾添加了.RESET_INDEX(DROP=True).
Method | 1000 rows | 10 000 rows | 100 000 rows |
---|---|---|---|
original | 556 ms | 5.41 s | Not tested |
mozway | 1.24 s | 10.1 s | Not tested |
Andrej Kesely | 696 ms | 4.56 s | Not tested |
Quang Hoang | 11.3 ms | 34.1 ms | 318 ms |