【问题标题】:Pandas: Get duplicated rows by key, if odd keep last, if even delete熊猫:按键获取重复的行,如果奇数保留最后,如果偶数删除
【发布时间】:2021-06-10 02:54:10
【问题描述】:

我面临需要处理付款和可能的撤销的情况。

当我将SUPPLIERDOC_ID 连接时,我有一个可以识别行是否重复的键。考虑到这一点,我想:

  1. 如果键重复且重复行数为偶数,则从数据集中删除行。
  2. 如果键重复并且重复行数为奇数,则保留最后一个条目并删除其他重复值。

数据示例:

INDEX   SUPPLIER    DOC_ID  VALUE
1       AAA         A       -539
2       OOO         B       -946
3       NNN         C       -320
4       HHH         D       -117
5       HHH         D        117
6       OOO         E       -741
7       AAA         F       -165
8       ZZZ         G       -103
9       ZZZ         G        103
10      ZZZ         G       -103
11      BBB         H       -504

在上面的数据集中,名称为 HSUPPLIER 有 2 行重复。这些行需要删除,因为它们相互抵消(-117+117=0)。

另一方面,名称ZZZSUPPLIER 有3 行重复。我需要保留最后一个条目,因为它是唯一有效的。其他人正在互相取消。

想要的输出:

INDEX   SUPPLIER    DOC_ID  VALUE
1       AAA         A       -539
2       OOO         B       -946
3       NNN         C       -320
6       OOO         E       -741
7       AAA         F       -165
10      ZZZ         G       -103
11      BBB         H       -504

【问题讨论】:

    标签: python python-3.x pandas dataframe duplicates


    【解决方案1】:

    你可以试试:

    # get the sizes
    sizes = df.groupby(['SUPPLIER','DOC_ID'])['VALUE'].transform('size')
    
    # duplicated
    duplicated = df.duplicated(['SUPPLIER','DOC_ID'], keep='last')
    
    
    df[(sizes%2==1)       # groups with odd number of rows
       & (~duplicated)    # and last rows
      ]
    

    输出:

          SUPPLIER DOC_ID  VALUE
    INDEX                       
    1          AAA      A   -539
    2          OOO      B   -946
    3          NNN      C   -320
    6          OOO      E   -741
    7          AAA      F   -165
    10         ZZZ      G   -103
    11         BBB      H   -504
    

    【讨论】:

    • filter: df.groupby(['SUPPLIER', 'DOC_ID']).filter(lambda d: len(d) % 2 == 1).drop_duplicates(['SUPPLIER', 'DOC_ID'])
    【解决方案2】:

    如果索引号不重要,这是一种相当简单的方法。 按 SUPPLIER 和 DOC_ID 分组并总结将消除重复项。所以在过滤掉 0 值之后会给你结果。

    grouped = data.groupby(['SUPPLIER', 'DOC_ID']).agg({'VALUE' : 'sum'}).reset_index()
    grouped = grouped.loc[grouped['VALUE'] != 0]
    

    这会给你这个结果。

        SUPPLIER DOC_ID VALUE
    0   AAA      A      -539
    1   AAA      F      -165
    2   BBB      H      -504
    4   NNN      C      -320
    5   OOO      B      -946
    6   OOO      E      -741
    7   ZZZ      G      -103
    
    

    【讨论】:

      【解决方案3】:

      我相信这个解决方案适用于您的情况,无论“价值”如何

      分组数据

      groups = df.groupby(["SUPPLIER", "DOC_ID"]).sum("VALUE")
      

      带有结果的新数据框

      df1 = groups.reset_index()
      

      删除零个结果

      df1 = df1[df1["VALUE"] != 0].sort_values("DOC_ID").reset_index()
      

      结果

         index SUPPLIER DOC_ID  INDEX  VALUE
      0      0      AAA      A      1   -539
      1      5      OOO      B      2   -946
      2      4      NNN      C      3   -320
      3      6      OOO      E      6   -741
      4      1      AAA      F      7   -165
      5      7      ZZZ      G     27   -103
      6      2      BBB      H     11   -504
      

      【讨论】:

        【解决方案4】:

        不是一个好的答案

        df.groupby(
            ['SUPPLIER', 'DOC_ID'],
            sort=False, as_index=False, group_keys=False
        ).apply(lambda d: d.tail(len(d) % 2))
        
            INDEX SUPPLIER DOC_ID  VALUE
        0       1      AAA      A   -539
        1       2      OOO      B   -946
        2       3      NNN      C   -320
        5       6      OOO      E   -741
        6       7      AAA      F   -165
        9      10      ZZZ      G   -103
        10     11      BBB      H   -504
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-05-06
          • 1970-01-01
          • 2017-05-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-18
          相关资源
          最近更新 更多