在Pandas中查找重复行,其中列值的顺序无关紧要

时间:2018-01-08 18:28:56

标签: python pandas numpy

示例数据框:

import pandas as pd

data = data = { 'num1': [1,2,3,4,5], 
        'num2': [1,1,2,3,1],
        'num3': [5,4,3,2,1]}

df = pd.DataFrame(data)

print(df.head())




>>> df.head()
   num1  num2  num3          
0     1     1     5                   #dups with row 4
1     2     1     4
2     3     2     3
3     4     3     2
4     5     1     1                  #dups with row 1

在此示例数据框中,我正在尝试提取第一行和最后一行, 因为他们的内容是彼此重复的(1,1,5)

如果值的顺序相同(似乎),下面的代码只会找到重复的行:

dups =df[df.duplicated(subset=None, keep='first')]

因此导致空数据集。

谢谢。

2 个答案:

答案 0 :(得分:4)

这是你想要的吗?

In [257]: df[pd.DataFrame(np.sort(df.values), columns=df.columns, index=df.index)
               .duplicated(keep='first')]
Out[257]:
   num1  num2  num3
4     5     1     1

或者如果您需要所有重复项:

In [258]: df[pd.DataFrame(np.sort(df.values), columns=df.columns, index=df.index)
               .duplicated(keep=False)]
Out[258]:
   num1  num2  num3
0     1     1     5
4     5     1     1

答案 1 :(得分:4)

方法#1:numpy.unique基于

以下一种方法使用最近添加的axis功能与np.unique -

In [64]: s = np.sort(df.values, axis=1)

In [65]: unq, tag, count = np.unique(s, axis=0, return_counts=1, return_inverse=1)

In [66]: df[np.in1d(tag, np.flatnonzero(count > 1))]
Out[66]: 
   num1  num2  num3
0     1     1     5
4     5     1     1

或者,最后一步可以简化 -

In [63]: df[count[tag] > 1]
Out[63]: 
   num1  num2  num3
0     1     1     5
4     5     1     1

方法#2:基于视图和索引排序

这个人专注于表现 -

# 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()

# Get duplicate rows indices off an array with order of elems being insensitive
def duprows_order_insensitive(ar): # ar is array
    s = np.sort(ar, axis=1)
    s_view1D = view1D(s)
    sidx = s_view1D.argsort()
    s_view1D_sorted = s_view1D[sidx]

    mask0 = s_view1D_sorted[1:] == s_view1D_sorted[:-1]
    mask = np.r_[False,mask0]
    mask[:-1] |= mask0
    return sidx[mask] # sort these if sorted indices are needed

因此,可以像这样获得所需的输出 -

df.iloc[duprows_order_insensitive(df.values)]

示例运行 -

In [234]: df
Out[234]: 
   num1  num2  num3
0     1     1     5
1     5     5     5
2     2     1     4
3     1     5     1
4     4     3     2
5     5     1     1
6     1     4     2

In [235]: df.iloc[duprows_order_insensitive(df.values)]
Out[235]: 
   num1  num2  num3
0     1     1     5
3     1     5     1
5     5     1     1
2     2     1     4
6     1     4     2