2016-11-07 56 views
6

我有一个数据框有两列,AB。在这种情况下,AB的顺序并不重要;例如,我会认为(0,50)(50,0)是重复的。在熊猫中,从数据框中删除这些重复项的有效方法是什么?熊猫:从数据框中删除相反的副本

import pandas as pd 

# Initial data frame. 
data = pd.DataFrame({'A': [0, 10, 11, 21, 22, 35, 5, 50], 
        'B': [50, 22, 35, 5, 10, 11, 21, 0]}) 
data 
    A B 
0 0 50 
1 10 22 
2 11 35 
3 21 5 
4 22 10 
5 35 11 
6 5 21 
7 50 0 

# Desired output with "duplicates" removed. 
data2 = pd.DataFrame({'A': [0, 5, 10, 11], 
         'B': [50, 21, 22, 35]}) 
data2 
    A B 
0 0 50 
1 5 21 
2 10 22 
3 11 35 

理想情况下,输出将按列A的值排序。

回答

9

可以丢弃重复之前排序的数据帧中的每一行:

data.apply(lambda r: sorted(r), axis = 1).drop_duplicates() 

# A B 
#0 0 50 
#1 10 22 
#2 11 35 
#3 5 21 

如果你喜欢的结果通过A列进行排序:

data.apply(lambda r: sorted(r), axis = 1).drop_duplicates().sort_values('A') 

# A B 
#0 0 50 
#3 5 21 
#1 10 22 
#2 11 35 
+3

不需要lambda,'.apply(sorted,axis = 1)'将会工作。 – root

+0

@root。那就对了。一个更好的选择。 – Psidom

+0

我喜欢这个答案!我想过的每件事都包含堆叠到数据框。这聪明消除了这种需要。 – piRSquared

4

这里是有点难看,但更快的解决方案:

In [44]: pd.DataFrame(np.sort(data.values, axis=1), columns=data.columns).drop_duplicates() 
Out[44]: 
    A B 
0 0 50 
1 10 22 
2 11 35 
3 5 21 

定时:对于8K行DF

In [50]: big = pd.concat([data] * 10**3, ignore_index=True) 

In [51]: big.shape 
Out[51]: (8000, 2) 

In [52]: %timeit big.apply(lambda r: sorted(r), axis = 1).drop_duplicates() 
1 loop, best of 3: 3.04 s per loop 

In [53]: %timeit pd.DataFrame(np.sort(big.values, axis=1), columns=big.columns).drop_duplicates() 
100 loops, best of 3: 3.96 ms per loop 

In [59]: %timeit big.apply(np.sort, axis = 1).drop_duplicates() 
1 loop, best of 3: 2.69 s per loop 
+1

这是矢量化实现的相同答案。不!丑陋的:-) – piRSquared