【问题标题】:Select rows from a Pandas DataFrame with same values in one column but different value in the other column从 Pandas DataFrame 中选择一列具有相同值但另一列具有不同值的行
【发布时间】:2019-05-31 06:48:24
【问题描述】:

假设我有下面的熊猫数据框:

   A      B     C   D
1  foo    one   0   0
2  foo    one   2   4
3  foo    two   4   8
4  cat    one   8   4
5  bar    four  6  12
6  bar    three 7  14
7  bar    four  7  14

我想选择在 A 中具有相同值但在 B 中具有不同值的所有行。所以我希望我的代码输出为:

   A      B    C   D
1  foo    one  0   0
3  foo    two  4   8
5  bar  three  7  14
6  bar    four 7  14

最有效的方法是什么?我有大约 11,000 行,列值有很多变化,但这种情况经常出现。在我的数据集中,如果 A 列中的元素相等,则相应的 B 列值也应该相等,但是由于标签错误,情况并非如此,我想解决这个问题,我这样做是不切实际的一。

【问题讨论】:

  • 为什么猫一不见了?
  • cat one 缺失,因为没有其他行使得“cat”是它的 A 值,但“one”不是它的 B 值。也许我的帖子不够清楚,对不起。

标签: python pandas dataframe select rows


【解决方案1】:

你可以试试groupby() + filter + drop_duplicates():

>>> df.groupby('A').filter(lambda g: len(g) > 1).drop_duplicates(subset=['A', 'B'], keep="first")
     A      B  C   D
0  foo    one  0   0
2  foo    two  4   8
4  bar   four  6  12
5  bar  three  7  14

或者,如果您想在列子集 AB 之间删除重复项,则可以在下面使用,但该行也将具有 cat

>>> df.drop_duplicates(subset=['A', 'B'], keep="first")
     A      B  C   D
0  foo    one  0   0
2  foo    two  4   8
3  cat    one  8   4
4  bar   four  6  12
5  bar  three  7  14

【讨论】:

    【解决方案2】:

    使用groupby + filter + head

    result = df.groupby('A').filter(lambda g: len(g) > 1).groupby(['A', 'B']).head(1)
    print(result)
    

    输出

         A      B  C   D
    0  foo    one  0   0
    2  foo    two  4   8
    4  bar   four  6  12
    5  bar  three  7  14
    

    第一个 group-by 和 filter 将删除没有重复 A 值的行(即 cat),第二个将创建具有相同 A, B 的组,并为每个组获取第一个元素。

    【讨论】:

    • 当我尝试这个时,我得到:unhashable type: 'dict'。供参考 type(df) 返回:<class 'pandas.core.frame.DataFrame'>type(df.A) 返回 <class 'pandas.core.series.Series'>
    • df.A的种类有哪些?
    • @apolanco115 好吧,我不知道是什么可能导致错误,我将示例加载到您的帖子中作为 csv 并且它可以工作。 dtype 也是对象。您的某一列似乎包含一本字典?
    【解决方案3】:

    当前的答案是正确的,也可能更复杂。如果您有复杂的标准,filter 函数将非常有用。如果你和我一样想保持简单,我觉得跟随是对初学者更友好的方式

    >>> df = pd.DataFrame({
        'A': ['foo', 'foo', 'foo', 'cat', 'bar', 'bar', 'bar'],
        'B': ['one', 'one', 'two', 'one', 'four', 'three', 'four'],
        'C': [0,2,4,8,6,7,7],
        'D': [0,4,8,4,12,14,14]
    }, index=[1,2,3,4,5,6,7])
    
    >>> df = df.drop_duplicates(['A', 'B'], keep='last')
        A       B       C   D
    2   foo     one     2   4
    3   foo     two     4   8
    4   cat     one     8   4
    6   bar     three   7   14
    7   bar     four    7   14
    
    
    >>> df = df[df.duplicated(['A'], keep=False)]
        A       B       C   D
    2   foo     one     2   4
    3   foo     two     4   8
    6   bar     three   7   14
    7   bar     four    7   14
    

    keep='last' 在这里是可选的

    【讨论】:

      猜你喜欢
      • 2017-02-14
      • 1970-01-01
      • 2012-05-25
      • 1970-01-01
      • 2017-12-24
      • 2015-07-17
      • 2022-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多