【问题标题】:Finding duplicate rows in Pandas, where order of column values don't matter在 Pandas 中查找重复行,其中列值的顺序无关紧要
【发布时间】:2018-06-17 18:31:49
【问题描述】:

示例数据框:

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')]

因此导致一个空数据集。

谢谢。

【问题讨论】:

    标签: python pandas numpy


    【解决方案1】:

    方法#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
    

    【讨论】:

    • @Divakar df[count[tag] > 1] 真的很聪明。
    【解决方案2】:

    这是你想要的吗?

    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
    

    【讨论】:

    • 这似乎也有效。我会玩弄你的答案以及上面的答案,看看哪一个看起来最好。谢谢。
    • @Moondra 如果你喜欢他们的回答,你可以投票 :-)
    猜你喜欢
    • 1970-01-01
    • 2020-01-20
    • 2016-08-23
    • 1970-01-01
    • 2017-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多