【问题标题】:Pandas: Remove limited duplicatesPandas:删除有限的重复项
【发布时间】:2018-02-19 15:25:49
【问题描述】:

所以,我有一个在运行时生成的文件。文件示例如下所示:

ID,Class_id,Column_A,Column_B,Column_C,Column_D,Mask
1,987,vermont,CA,450,liase,2
2,456,WB,cloo,452,var,1
3,987,CA,Cp,1000000,liase,2
4,456,SA,Cap,98376,clop,1
5,765,IN,clas,543,king,2
6,987,SA,CLA,200,loop,2
7,456,BEG,loop,876,var,1

如您所见,Class_id 存在重复元素。 Mask 还指定了文件中可以存在的重复元素的最大数量。

我要做的是逐个删除重复元素的最后一次出现,直到重复记录的数量与其Mask值相同。

如果是上述文件,

Class_id 中的 987 次出现了 3 次。它的Mask 值为 2。因此它最多只能出现 2 次。所以我需要删除最后一次出现的 987,这是第 6 条记录。文件中记录的顺序在这里无关紧要。

我想要得到的输出是这样的:

ID,Class_id,Column_A,Column_B,Column_C,Column_D,Mask
1,987,vermont,CA,450,liase,2
3,987,CA,Cp,1000000,liase,2
2,456,WB,cloo,452,var,5
5,765,IN,clas,543,king,2

我浏览了这个网站,但找不到可行的解决方案。这些是我引用的网站;

Pandas: remove reverse duplicates from dataframe Find Duplicates limited to multiple ranges - pandas python pandas remove duplicate columns How to conditionally remove duplicates from a pandas dataframe Drop all duplicate rows in Python Pandas

我注意到 Python 有一个 drop_duplicates 函数。坚果我如何限制要删除的重复项的数量?

有人可以帮助这里的新手吗?谢谢。

【问题讨论】:

    标签: python python-2.7 pandas


    【解决方案1】:

    使用boolean indexing 与掩码比较Series by cumcount 与列Masklt (<):

    df = df[df.groupby('Class_id').cumcount().lt(df.Mask)]
    print (df)
    
       ID  Class_id Column_A Column_B  Column_C Column_D  Mask
    0   1       987  vermont       CA       450    liase     2
    1   2       456       WB     cloo       452      var     1
    2   3       987       CA       Cp   1000000    liase     2
    4   5       765       IN     clas       543     king     2
    

    详情

    print (df.groupby('Class_id').cumcount())
    0    0
    1    0
    2    1
    3    1
    4    0
    5    2
    6    2
    dtype: int64
    

    【讨论】:

      【解决方案2】:

      使用cumcount 解决修剪多余行的问题。使用pd.factorize + np.bincount 过滤掉行数少于Mask的行

      mask = df.Mask.values
      f, u = pd.factorize(df.Class_id.values)
      
      cond1 = df.groupby('Class_id').cumcount().lt(mask)
      cond2 = np.bincount(f)[f] >= mask
      
      df[cond1 & cond2]
      
         ID  Class_id Column_A Column_B  Column_C Column_D  Mask
      0   1       987  vermont       CA       450    liase     2
      1   2       456       WB     cloo       452      var     1
      2   3       987       CA       Cp   1000000    liase     2
      

      您会注意到,这 不是 OP 所希望的输出。该输出与 EQUALMask 列中的值的行数不一致。


      另一种使用transform('size') 而不是pd.factorize 来消除计数太小的行的方法。

      g = df.groupby('Class_id')
      
      mask = df.Mask.values
      cond1 = g.cumcount().lt(mask)
      cond2 = g.ID.transform('size').ge(mask)
      
      df[cond1 & cond2]
      
         ID  Class_id Column_A Column_B  Column_C Column_D  Mask
      0   1       987  vermont       CA       450    liase     2
      1   2       456       WB     cloo       452      var     1
      2   3       987       CA       Cp   1000000    liase     2
      

      【讨论】:

      • 刚刚发表评论。
      • 我很困惑,缺少什么?
      • 基于OP的话“直到重复记录的数量与其Mask值相同” 意图是模棱两可的。我假设它们意味着'Class_id' 的元素数等于Mask 列中的值。可能你所拥有的正是他们想要的,也是我最初所做的。但我注意到了这一点并想解决它。
      【解决方案3】:

      使用cumcount

      In [260]: df[df.groupby('Class_id').cumcount() < df['Mask']]
      Out[260]:
         ID  Class_id Column_A Column_B  Column_C Column_D  Mask
      0   1       987  vermont       CA       450    liase     2
      1   2       456       WB     cloo       452      var     1
      2   3       987       CA       Cp   1000000    liase     2
      4   5       765       IN     clas       543     king     2
      

      【讨论】:

        猜你喜欢
        • 2019-02-02
        • 1970-01-01
        • 2021-02-24
        • 1970-01-01
        • 2017-03-10
        • 2012-10-09
        • 2018-05-13
        • 2022-11-21
        相关资源
        最近更新 更多