【问题标题】:Drop duplicates, but keep rows with highest value including ties删除重复项,但保留具有最高值的行,包括平局
【发布时间】:2019-01-02 14:10:39
【问题描述】:

我想删除 col1 的重复值,只保存 col2 中具有最高值的行。例子df:

df1 = pd.DataFrame({'col1': ['a', 'a', 'b', 'b', 'c'],
                   'col2': [5, 5, 10, 15, 20]})

我知道df1.drop_duplicates 会删除重复值,但我如何确保它是保存的最高值(或多个值,如果有与最高值相关的值)?

期望的输出:

dfoutput = pd.DataFrame({'col1': ['a', 'a', 'b', 'c'],
                       'col2': [5, 5, 15, 20]})

【问题讨论】:

    标签: python pandas dataframe duplicates


    【解决方案1】:

    您可以使用 Pandas 的rank 功能:

    为组的每一行分配排名。如果值相同,则行将具有相同的排名。如下所示:

    In [126]: df1['rnk'] = df1.groupby('col1')['col2'].rank()
    In [127]: df1
    Out[127]: 
      col1  col2  rnk
    0    a     5  1.5
    1    a     5  1.5
    2    b    10  1.0
    3    b    15  2.0
    4    c    20  1.0
    

    然后使用query的方法只过滤小于2.0的排名:

    In [129]: df1.query('rnk < 2.0').drop('rnk',1)
    Out[129]: 
      col1  col2
    0    a     5
    1    a     5
    2    b    10
    4    c    20
    

    可以结合以上两个命令得到1行解决方案:

    In [130]: df1[df1.groupby('col1')['col2'].rank() < 2]
    Out[130]: 
      col1  col2
    0    a     5
    1    a     5
    2    b    10
    4    c    20
    

    【讨论】:

    • 有趣的解决方案!
    • 其实不需要多出一列,只要df1[df1.groupby('col1')['col2'].rank() &lt; 2]就行了。
    • 是的,我知道不需要额外的列。放在那里是为了理解OP。
    【解决方案2】:

    首先按降序对 DataFrame 进行排序。接下来,计算两个掩码,一个用于确定其组中的最大行数,另一个用于确定哪些行是重复的。

    然后我们可以结合这些掩码来确定哪些行是重复的不是它们各自组中的最大值,并执行最后一个过滤步骤。

    v = df1.sort_values('col2', ascending=False)
    m1 = v['col2'] == v.groupby('col1', sort=False)['col2'].transform('max')
    m2 = v.duplicated('col1')
    
    v[~(m2 & ~m1)].sort_index()   # v[~m2 | m1] - DeMorgan's Law
    
      col1  col2
    0    a     5
    1    a     5
    3    b    15
    4    c    20
    

    【讨论】:

    • 我更喜欢第一个,它提供了 OP 希望的输出。 :)
    • @anky_91 谢谢!没想到结果有出入!也为你 +1 了。
    【解决方案3】:

    我发现的另一种方式:

    在按decending order 排序后获取重复项并附加去重值,然后删除重复的索引。

    dfoutput = df1[df1.duplicated(keep=False)].append(df1.sort_values(['col1','col2'],ascending=False).drop_duplicates(['col1']))
    dfoutput[~dfoutput.index.duplicated()].sort_index()
    
        col1    col2
    0   a       5
    1   a       5
    3   b       15
    4   c       20
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-10
      • 2018-12-29
      • 2012-09-11
      • 1970-01-01
      • 2019-10-27
      • 2015-10-05
      • 2012-09-30
      • 2015-03-19
      相关资源
      最近更新 更多