from itertools import product
import pandas as pd
df = pd.DataFrame.from_records(product(range(10), range(10)))
df = df.sample(90)
df.columns = "c1 c2".split()
df = df.sort_values(df.columns.tolist()).reset_index(drop=True)
# c1 c2
# 0 0 0
# 1 0 1
# 2 0 2
# 3 0 3
# 4 0 4
# .. .. ..
# 85 9 4
# 86 9 5
# 87 9 7
# 88 9 8
# 89 9 9
#
# [90 rows x 2 columns]
如何快速查找,识别和删除此数据帧中所有对称对的最后一个重复项?
对称对的一个示例是'(0,1)'等于'(1,0)'。后者应删除。
该算法必须快速,因此建议使用numpy。不允许转换为python对象。
答案 0 :(得分:14)
您可以对值进行排序,然后对groupby
:
a= np.sort(df.to_numpy(), axis=1)
df.groupby([a[:,0], a[:,1]], as_index=False, sort=False).first()
选项2 :如果c1, c2
对很多,groupby
可能会变慢。在这种情况下,我们可以分配新值并按drop_duplicates
进行过滤:
a= np.sort(df.to_numpy(), axis=1)
(df.assign(one=a[:,0], two=a[:,1]) # one and two can be changed
.drop_duplicates(['one','two']) # taken from above
.reindex(df.columns, axis=1)
)
答案 1 :(得分:7)
一种方法是将np.unique
与return_index=True
一起使用,并使用结果为数据帧编制索引:
a = np.sort(df.values)
_, ix = np.unique(a, return_index=True, axis=0)
print(df.iloc[ix, :])
c1 c2
0 0 0
1 0 1
20 2 0
3 0 3
40 4 0
50 5 0
6 0 6
70 7 0
8 0 8
9 0 9
11 1 1
21 2 1
13 1 3
41 4 1
51 5 1
16 1 6
71 7 1
...
答案 2 :(得分:5)
frozenset
mask = pd.Series(map(frozenset, zip(df.c1, df.c2))).duplicated()
df[~mask]
答案 3 :(得分:5)
我会做
df[~pd.DataFrame(np.sort(df.values,1)).duplicated().values]
来自熊猫和numpy tri
s=pd.crosstab(df.c1,df.c2)
s=s.mask(np.triu(np.ones(s.shape)).astype(np.bool) & s==0).stack().reset_index()
答案 4 :(得分:4)
这是一个基于NumPy的整数-
def remove_symm_pairs(df):
a = df.to_numpy(copy=False)
b = np.sort(a,axis=1)
idx = np.ravel_multi_index(b.T,(b.max(0)+1))
sidx = idx.argsort(kind='mergesort')
p = idx[sidx]
m = np.r_[True,p[:-1]!=p[1:]]
a_out = a[np.sort(sidx[m])]
df_out = pd.DataFrame(a_out)
return df_out
如果要保持索引数据不变,请使用return df.iloc[np.sort(sidx[m])]
。
对于通用数字(整数/浮点数等),我们将使用view-based
一个-
# https://stackoverflow.com/a/44999009/ @Divakar
def view1D(a): # a is array
a = np.ascontiguousarray(a)
void_dt = np.dtype((np.void, a.dtype.itemsize * a.shape[1]))
return a.view(void_dt).ravel()
,只需替换在idx
中用idx = view1D(b)
获得remove_symm_pairs
的步骤即可。
答案 5 :(得分:1)
如果这需要快速,并且您的变量是整数,那么以下技巧可能会有所帮助:让v,w
为向量的列;构造[v+w, np.abs(v-w)] =: [x, y]
;然后按字典顺序排序此矩阵,删除重复项,最后将其映射回[v, w] = [(x+y), (x-y)]/2
。