【问题标题】:Pandas: DataFrame filtering using groupby and a functionPandas:使用 groupby 和函数进行 DataFrame 过滤
【发布时间】:2013-07-30 19:47:46
【问题描述】:

使用 Python 3.3 和 Pandas 0.10

我有一个通过连接多个 CSV 文件构建的 DataFrame。首先,我过滤掉 Name 列中包含某个字符串的所有值。结果看起来像这样(为简洁起见缩短了,实际上还有更多列):

Name    ID
'A'     1
'B'     2
'C'     3
'C'     3
'E'     4
'F'     4
...     ...

现在我的问题是我想删除“重复”值的特殊情况。我想删除映射到此 ID 的相应名称值相似的所有 ID 重复项(实际上是整行)。在上面的示例中,我想保留 ID 为 1、2 和 3 的行。其中 ID=4 的 Name 值不相等,我想删除它们。

我尝试使用以下代码行(基于此处的建议:Python Pandas: remove entries based on the number of occurrences)。

代码:

df[df.groupby('ID').apply(lambda g: len({x for x in g['Name']})) == 1]

但是,这给了我错误: ValueError: Item wrong length 51906 instead of 109565!

编辑:

我也尝试使用transform(),而不是使用apply(),但是这给了我错误:AttributeError: 'int' object has no attribute 'ndim'。非常感谢您解释为什么每个函数的错误不同!

另外,我想保留上面示例中 ID = 3 的所有行。

提前致谢, 马蒂斯

【问题讨论】:

    标签: python python-3.x pandas


    【解决方案1】:

    而不是长度len,我认为您想考虑每组中Name 的唯一值的数量。使用nunique(),并查看这个用于过滤组的简洁配方。

    df[df.groupby('ID').Name.transform(lambda x: x.nunique() == 1).astype('bool')]
    

    如果您升级到 pandas 0.12,您可以在组上使用新的filter 方法,这使得这更加简洁明了。

    df.groupby('ID').filter(lambda x: x.Name.nunique() == 1)
    

    一般性评论:当然,有时您确实想知道组的长度,但我发现sizelen 更安全,这在某些情况下对我来说很麻烦。

    【讨论】:

    • 我总是忘记变换! :)
    • 哈哈。人们通常不会发现它——我想我至少每周回答一次转换问题。
    • 嘿,丹,谢谢!明天我将不得不尝试您的代码,但到目前为止这对我来说很有意义。我不知道nunique() 所以也感谢您指出这一点。实际上,您能否简要描述一下您为什么使用transform() 而不是apply()
    • apply 将返回一个较短的系列,每组一个条目。相反,我们想要一个与原始序列长度相同的序列,每个组的全部内容都映射到TrueFalse 作为一个块。然后我们可以使用该布尔系列来掩盖原始系列。请参阅documentation 了解更多信息。
    • 嗨,丹,我刚刚运行了你的代码,它就像一个魅力。也感谢 transform()apply() 的解释!
    【解决方案2】:

    您可以先删除重复项:

    In [11]: df = df.drop_duplicates()
    
    In [12]: df
    Out[12]:
      Name ID
    0    A  1
    1    B  2
    2    C  3
    4    E  4
    5    F  4
    

    groupby id 并且只考虑具有一个元素的那些:

    In [13]: g = df.groupby('ID')
    
    In [14]: size = (g.size() == 1)
    
    In [15]: size
    Out[15]:
    ID
    1      True
    2      True
    3      True
    4     False
    dtype: bool
    
    In [16]: size[size].index
    Out[16]: Int64Index([1, 2, 3], dtype=int64)
    
    In [17]: df['ID'].isin(size[size].index)
    Out[17]:
    0     True
    1     True
    2     True
    4    False
    5    False
    Name: ID, dtype: bool
    

    布尔索引是这样的:

    In [18]: df[df['ID'].isin(size[size].index)]
    Out[18]:
      Name ID
    0    A  1
    1    B  2
    2    C  3
    

    【讨论】:

    • 感谢您的帮助,安迪,但我会接受丹的回答。
    • @Matthijs 更好:)
    猜你喜欢
    • 2020-11-29
    • 2022-11-03
    • 2016-11-04
    • 1970-01-01
    • 2023-03-29
    • 2021-06-29
    • 1970-01-01
    • 2021-10-04
    • 2022-11-15
    相关资源
    最近更新 更多