我有以下熊猫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))]
任何帮助表示赞赏!谢谢
答案 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)]))