【问题标题】:Python - Delete duplicates in a dataframe based on two columns combinations?Python - 根据两列组合删除数据框中的重复项?
【发布时间】:2018-12-13 09:36:11
【问题描述】:

我在 Python 中有一个包含 3 列的数据框:

Name1 Name2 Value
Juan  Ale   1
Ale   Juan  1

并希望消除基于列 Name1 和 Name2 组合的重复项。

在我的示例中,两行是相等的(但它们的顺序不同),我想删除第二行,只保留第一行,所以最终结果应该是:

Name1 Name2 Value
Juan  Ale   1

任何想法都会非常感激!

【问题讨论】:

    标签: python pandas sorting dataframe


    【解决方案1】:

    通过使用np.sortduplicated

    df[pd.DataFrame(np.sort(df[['Name1','Name2']].values,1)).duplicated()]
    Out[614]: 
      Name1 Name2  Value
    1   Ale  Juan      1
    

    性能

    df=pd.concat([df]*100000)
    
    %timeit df[pd.DataFrame(np.sort(df[['Name1','Name2']].values,1)).duplicated()]
    10 loops, best of 3: 69.3 ms per loop
    %timeit df[~df[['Name1', 'Name2']].apply(frozenset, axis=1).duplicated()]
    1 loop, best of 3: 3.72 s per loop
    

    【讨论】:

    • 这比frozenset方法好100倍。
    • @coldspeed 是的,即使排序匹配得很快,我仍然牢记您的建议,apply 效率较低。 :-)
    • 谢谢!超级快!我不得不做一个小改变,因为它正在提高:'IndexingError: Unalignable boolean Series provided as indexer (index of the boolean Series and of the indexed object do not match)' 但这成功了:df[pd.DataFrame(np.sort(df[['Name1','Name2']].values,1)).duplicated().values]
    【解决方案2】:

    您可以转换为frozenset 并使用pd.DataFrame.duplicated

    res = df[~df[['Name1', 'Name2']].apply(frozenset, axis=1).duplicated()]
    
    print(res)
    
      Name1 Name2  Value
    0  Juan   Ale      1
    

    frozenset 是必需的,而不是 set,因为 duplicated 使用散列来检查重复项。

    列比行更好。对于大量行,使用@Wen 的基于排序的算法。

    【讨论】:

      【解决方案3】:

      知道我回答这个问题有点晚了,但无论如何都要做出贡献:)

      您还可以使用get_dummiesadd 来创建可散列的行

      df[~(pd.get_dummies(df.a).add(pd.get_dummies(df.b), fill_value=0)).duplicated()]
      

      时间不如@Wen 的回答,但还是比apply+frozen_set快很多

      df=pd.concat([df]*1000000)
      %timeit df[~(pd.get_dummies(df.a).add(pd.get_dummies(df.b), fill_value=0)).duplicated()]
      1.8 s ± 85 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
      
      %timeit df[pd.DataFrame(np.sort(df[['a','b']].values,1)).duplicated()]
      1.26 s ± 19 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
      
      %timeit df[~df[['a', 'b']].apply(frozenset, axis=1).duplicated()]
      1min 9s ± 684 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
      

      【讨论】:

      • 有趣..get_dummies为此目的非常创新:)
      猜你喜欢
      • 1970-01-01
      • 2017-03-02
      • 2021-02-09
      • 2021-05-14
      • 1970-01-01
      • 2021-03-20
      • 1970-01-01
      • 2019-05-12
      • 2021-01-01
      相关资源
      最近更新 更多