我试图一次遍历我的数据框两行,检查两行中的列值是否相同,然后删除此类行。我的数据框跟踪在不同遭遇中不同人的位置。
我有一个名为transfers
的数据框,其中的每一行都包含一个人的ID号,一个相遇号和一个位置。 transfers
数据帧是通过在原始数据帧上运行重复项以查找具有相同个人ID的行并将它们分组在一起而创建的。
例如,我们希望摆脱下面数据框中带有ID = 2
的行,因为在两次遭遇中该位置均为"D"
,因此此人没有移动。
但是,我们希望保留ID = 3
的行,因为该人从"A"
移到"F"
。
出现另一个问题是因为某些人有两行以上,例如ID = 1
。对于此人,我们希望保留它们的行,因为它们已从"A"
-> "B"
移动,然后又从"B"
-> "C"
移动。但是,如果您仅比较遭遇12和13,则看起来此人似乎没有改变位置。
示例数据帧df
:
ID Encounter Location
1 11 A
1 12 B
1 13 B
1 14 C
2 21 D
2 22 D
3 31 A
3 32 F
预期输出:
ID Encounter Location
1 11 A
1 12 B
1 13 B
1 14 C
3 31 A
3 32 F
我已经尝试过使用for
进行嵌套的.iterrows()
循环,但是我发现这行不通,因为它非常慢,并且不能正确处理该人遇到两次以上的情况。我也尝试将一个函数应用于我的数据框,但是运行时与粗循环几乎相同。
编辑:我应该明确指出这一点,我试图保留已移动位置的任何人的数据,即使他们最终回到起点。
答案 0 :(得分:4)
给予
>>> df
ID Encounter Location
0 1 11 A
1 1 12 B
2 1 13 B
3 1 14 C
4 2 21 D
5 2 22 D
6 3 31 A
7 3 32 F
您可以通过以下方式过滤数据框
>>> places = df.groupby('ID')['Location'].transform('nunique')
>>> df[places > 1]
ID Encounter Location
0 1 11 A
1 1 12 B
2 1 13 B
3 1 14 C
6 3 31 A
7 3 32 F
想法是计算每组(ID)的唯一位置的数量,然后将一个人仅曾到过一个地方的行删除。
与filter
解决方案的比较:
# setup
>>> df = pd.concat([df.assign(ID=df['ID'] + i) for i in range(1000)], ignore_index=True)
>>> df
ID Encounter Location
0 1 11 A
1 1 12 B
2 1 13 B
3 1 14 C
4 2 21 D
... ... ... ...
7995 1000 14 C
7996 1001 21 D
7997 1001 22 D
7998 1002 31 A
7999 1002 32 F
[8000 rows x 3 columns]
# timings @ i5-6200U CPU @ 2.30GHz
>>> %timeit df.groupby('ID').filter(lambda x: x['Location'].nunique() > 1)
356 ms ± 19.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
>>> %timeit df[df.groupby('ID')['Location'].transform('nunique') > 1]
5.56 ms ± 21.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)