代码之家  ›  专栏  ›  技术社区  ›  Coder927

如果重复计数大于1并且符合条件,Pandas数据帧将删除重复项

  •  0
  • Coder927  · 技术社区  · 2 年前

    我有这样的数据:

    data = [['ABC','A','Good Value'], ['DEF','V','Good Value'], ['ABC','A','Unclear Value'], ['XYZ','B','Good Value'], ['LMN','N','Unclear Value'], ['JKL','M','Best Value'], ['ABC','A','Better Value'], ['JKL','M','Good Value']] 
    
    df = pd.DataFrame(data, columns=['Name', 'Class', 'Value'])
    
    # 名称 价值
    1. 基础知识 A. 良好的价值
    2. DEF 五、 良好的价值
    3. 基础知识 A. 不清楚的值
    4. XYZ B 良好的价值
    5. LMN N 不清楚的值
    6. JKL M 最佳价值
    7. 基础知识 A. 更好的价值
    8. JKL M 良好的价值

    仅当存在重复项时,我希望删除列[“Name”,“Class”]上的重复项。如果['Name','Class']组合只有一个条目,则保留它。此外,当列['Name],'Class']上存在重复项时,仅当值为'Unclear value'时才删除它。

    因此,预期的输出是去除第3行,保留第1行和第7行。#6和#8都被保留,因为它们都不是“未知值”#5被保留,因为它是唯一一个具有名称LMN和类N的行,所以即使它有Unclear值,也应该保留它。

    到目前为止,我所拥有的是所有可能的价值观的优先列表。如[“Good value”、“Best value”、“Better value”和“Unclear value”],其中Unclear value是列表中的最后一个。然后我将Value列转换为Pandas Categorical

    df.Value = pd.Categorical(df.Value, categories=['Good Value', 'Best Value', 'Better Value', 'Unclear Value'],ordered=True)
    

    然后这样做:

    df.sort_values('Value').groupby(['Name', 'Class']).first()
    

    我在使用这种方法时遇到的问题是#6和#8中的一个被丢弃了。此外,3行#1、#3、#7中只有一行被保留,而我只希望#3被丢弃。

    另一件事是,这个优先级列表实际上只是为了让我保持一个好的值而不是一个不清楚的值。实际上没有提供这样的优先权清单。我自己定义这一点,所以我可以在最低优先级上保持不清楚,这样它就可能被放弃。我宁愿根本没有优先事项清单。

    到目前为止,我唯一能想到的方法就是通过进行分组并获得唯一的值计数。然后在count为>的组上迭代;1,对于每个这样的组,去掉值为“Unclear value”的行。但我不想迭代数据,所以我想寻找一个更复杂的解决方案。

    2 回复  |  直到 2 年前
        1
  •  1
  •   mozway    2 年前

    您可以使用 boolean indexing 有两个口罩:

    # is the Name/Class combination duplicated?
    m1 = df[['Name', 'Class']].duplicated(keep=False)
    # is the Value "Unclear Value"?
    m2 = df['Value'].eq('Unclear Value')
    
    # drop if both conditions are met
    out = df[~(m1&m2)]
    

    输出

      Name Class          Value
    0  ABC     A     Good Value
    1  DEF     V     Good Value
    3  XYZ     B     Good Value
    4  LMN     N  Unclear Value
    5  JKL     M     Best Value
    6  ABC     A   Better Value
    7  JKL     M     Good Value
    

    中间体:

      Name Class          Value     m1     m2  m1&m2  ~(m1&m2)
    0  ABC     A     Good Value   True  False  False      True
    1  DEF     V     Good Value  False  False  False      True
    2  ABC     A  Unclear Value   True   True   True     False
    3  XYZ     B     Good Value  False  False  False      True
    4  LMN     N  Unclear Value  False   True  False      True
    5  JKL     M     Best Value   True  False  False      True
    6  ABC     A   Better Value   True  False  False      True
    7  JKL     M     Good Value   True  False  False      True
    
        2
  •  0
  •   Corralien    2 年前

    与@mozway的逻辑相同 Categorical :

    cat = pd.CategoricalDtype(['Good Value', 'Best Value', 'Better Value',
                               'Unclear Value'], ordered=True)
    
    cnt = (df.astype({'Value': cat}).sort_values('Value')
             .groupby(['Name', 'Class']).cumcount())
    
    out = df[~(df['Value'].eq('Unclear Value') & cnt.gt(1))]
    

    输出

    >>> out
      Name Class          Value  count
    1  ABC     A     Good Value      0
    2  DEF     V     Good Value      0
    4  XYZ     B     Good Value      0
    5  LMN     N  Unclear Value      0
    6  JKL     M     Best Value      1
    7  ABC     A   Better Value      1
    8  JKL     M     Good Value      0