删除人员未更改位置的行

时间:2019-01-05 20:13:48

标签: python pandas numpy dataframe

我试图一次遍历我的数据框两行,检查两行中的列值是否相同,然后删除此类行。我的数据框跟踪在不同遭遇中不同人的位置。

我有一个名为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()循环,但是我发现这行不通,因为它非常慢,并且不能正确处理该人遇到两次以上的情况。我也尝试将一个函数应用于我的数据框,但是运行时与粗循环几乎相同。

编辑:我应该明确指出这一点,我试图保留已移动位置的任何人的数据,即使他们最终回到起点。

1 个答案:

答案 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)