如何删除熊猫数据框中的“镜像副本”行?

时间:2019-10-22 20:51:02

标签: python pandas dataframe subset

我有以下熊猫DataFrame在A-B-E和C-D-F之间具有“镜像副本”行:

import numpy as np
import pandas as pd

df1 = pd.DataFrame(np.array([[1, 2, 3, 4, 47, 27], [5, 6, 7, 8, 21, 40], [9, 10, 11, 12, 45, 33], 
    [3, 4, 1, 2, 27, 47], [7, 8, 5, 6, 40, 21], [11, 12, 9, 10, 33, 45]]), 
    columns=['A', 'B', 'C', 'D', 'E', 'F'])

print(df1)

##     A   B   C   D   E   F
## 0   1   2   3   4  47  27
## 1   5   6   7   8  21  40
## 2   9  10  11  12  45  33
## 3   3   4   1   2  27  47
## 4   7   8   5   6  40  21
## 5  11  12   9  10  33  45

“镜像副本”的意思是:如果您查看第3、4、5行,则它们是第0、1、2行的“镜像副本”。是第3、4、5行中的C和D列。

例如,在第0行中,['A','B','C','D']为[1、2、3、4]。在第3行中,['A','B','C','D']为[3、4、1、2]。

对于E和F列也是如此--第0、1、2行中的E值是第3、4、5行中的F值。

我想删除这些“镜像副本”行,而只保留“唯一”对。上面的正确输出应为:

##     A   B   C   D   E   F
## 0   1   2   3   4  47  27
## 1   5   6   7   8  21  40
## 2   9  10  11  12  45  33

##     A   B   C   D   E   F
## 0   3   4   1   2  27  47
## 1   7   8   5   6  40  21
## 2  11  12   9  10  33  45

但不能同时使用---只能复制一行。

我不知道如何将熊猫DataFrame子集化以删除这些行。如何以一种算法高效的方式(不增加内存)做到这一点?

我的第一个想法是错误的,因为它仅检查每行:

df1 = df1[~((df1.A == df1.C) & (df1.B == df1.D) & (df1.E == df1.F))]

任何帮助表示赞赏!谢谢

1 个答案:

答案 0 :(得分:2)

您可以执行以下操作:

from collections import Counter

import numpy as np
import pandas as pd


def key(x):
    return frozenset(Counter(x).items())


df = pd.DataFrame(np.array([[1, 2, 3, 4, 47, 27], [5, 6, 7, 8, 21, 40], [9, 10, 11, 12, 45, 33],
                            [3, 4, 1, 2, 27, 47], [7, 8, 5, 6, 40, 21], [11, 12, 9, 10, 33, 45]]),
                  columns=['A', 'B', 'C', 'D', 'E', 'F'])

keys = df[['A', 'B', 'C', 'D', 'E', 'F']].apply(key, axis=1)
mask = keys.duplicated(keep='last')

print(df[mask])

输出

   A   B   C   D   E   F
0  1   2   3   4  47  27
1  5   6   7   8  21  40
2  9  10  11  12  45  33

想法是创建一个keys列(系列),该列在彼此镜像的那些行上具有相同的值。

此:

def key(x):
    return frozenset(Counter(x).items())


keys = df[['A', 'B', 'C', 'D', 'E', 'F']].apply(key, axis=1)

创建keys列,然后标记重复的值:

mask = keys.duplicated(keep='last')

您还可以使用@piRSquared建议的密钥:

def key(x): 
    a, b, c, d, e, f = x
    return tuple(map(frozenset, [(a, c), (b, d), (e, f)]))