【问题标题】:Drop duplicates based on majority rule根据多数规则删除重复项
【发布时间】:2018-10-25 15:28:28
【问题描述】:

我有一个如下所示的表格:

A  B
1  cat
1  cat
1  dog
2  illama
2  alpaca
3  donkey

使用 A 作为键,我想删除重复项,使该数据框变为:

A  B
1  cat
3  donkey

1 重复了 3 次,cat 出现次数最多,因此被记录下来。 2 没有多数,因此它被认为是模棱两可的并被完全删除。 3 保持不变,因为它没有重复。

【问题讨论】:

    标签: python pandas dataframe duplicates


    【解决方案1】:

    groupby + pd.Series.mode

    这是使用pd.Series.mode 的两步解决方案:

    # find the mode for each group
    i = df.groupby('A').B.apply(pd.Series.mode).reset_index(level=1, drop=True)
    # filter out groups which have more than one mode—ambiguous groups
    j = i[i.groupby(level=0).transform('count') == 1].reset_index()
    

    print(j)
    
       A       B
    0  1     cat
    1  3  donkey
    

    groupby + <自定义函数>

    或者,定义一个计算模式的自定义函数并使用apply 调用它。过滤逻辑包含在函数中。

    def foo(x):
        m = pd.Series.mode(x)
        if len(m) == 1: 
            return m
    
    df.groupby('A').B.apply(foo).reset_index(level=1, drop=True).reset_index()
    
       A       B
    0  1     cat
    1  3  donkey
    

    【讨论】:

    • 您的代码对我有用,谢谢!有没有办法将输出作为数据框保留 B 作为值的列名?
    • @AndyG 已编辑,现在看看?
    【解决方案2】:

    使用value_countsrank怎么样:

    df.groupby('A')['B'].apply(lambda x: x.value_counts().rank(ascending=False)).eq(1)[lambda x: x].reset_index()
    

    输出:

       A level_1     B
    0  1     cat  True
    1  3  donkey  True
    

    使用 rank with method='average' 作为投票者,从 value_count 的结果中获得“多数”。

    【讨论】:

      【解决方案3】:

      您可以使用statistics.mode,如果不存在唯一模式,则会引发StatisticsError

      from statistics import mode, StatisticsError
      
      def moder(x):
          try:
              return mode(x)
          except StatisticsError:
              return None
      
      res = df.groupby('A')['B'].apply(moder)\
              .dropna().reset_index()
      
      print(res)
      
         A       B
      0  1     cat
      1  3  donkey
      

      性能基准测试

      虽然所有 3 种方法都适合您的任务,但它们的性能略有不同。

      基准测试结果:

      df = pd.concat([df]*10000)
      
      %timeit jpp(df)  # 18.3 ms ± 414 µs per loop
      %timeit cs1(df)  # 28.1 ms ± 558 µs per loop
      %timeit cs2(df)  # 24.5 ms ± 595 µs per loop
      

      基准代码:

      from statistics import mode, StatisticsError
      
      def moder(x):
          try:
              return mode(x)
          except StatisticsError:
              return None
      
      def foo(x):
          m = pd.Series.mode(x)
          if len(m) == 1: 
              return m
      
      def jpp(df):
          return df.groupby('A')['B'].apply(moder)\
                   .dropna().reset_index()
      
      def cs1(df):
          i = df.groupby('A').B.apply(pd.Series.mode).reset_index(level=1, drop=True)
          return i[i.groupby(level=0).transform('count') == 1].reset_index()
      
      def cs2(df):
          return df.groupby('A').B.apply(foo).reset_index(level=1, drop=True).reset_index()
      

      【讨论】:

        猜你喜欢
        • 2019-01-14
        • 2021-12-27
        • 2013-03-12
        • 1970-01-01
        • 2022-08-15
        • 1970-01-01
        • 1970-01-01
        • 2016-09-16
        • 2021-02-09
        相关资源
        最近更新 更多