【问题标题】:Pandas groupby and filter熊猫 groupby 和过滤器
【发布时间】:2017-05-22 06:04:45
【问题描述】:

我有数据框:

df = pd.DataFrame({'ID':[1,1,2,2,3,3], 
                   'YEAR' : [2011,2012,2012,2013,2013,2014], 
                   'V': [0,1,1,0,1,0],
                   'C':[00,11,22,33,44,55]})

我想按 ID 分组,并在每个组中选择 V = 0 的行。

这似乎不起作用:

print(df.groupby(['ID']).filter(lambda x: x['V'] == 0)) 

出现错误:

TypeError:过滤器函数返回一个系列,但期望一个标量布尔

如何使用过滤器来实现目标?谢谢。

编辑: V 上的条件可能因每个组而异,例如,对于 ID 1,它可能是 V==0,对于 ID 2,它可能是 V==1,并且可以通过另一个 DF 获得此信息:

df = pd.DataFrame({'ID':[1,2,3], 
                   'V': [0,1,0])

那么如何在每个组内进行行过滤呢?

【问题讨论】:

    标签: python pandas indexing group-by conditional-statements


    【解决方案1】:

    我认为groupby 不是必需的,仅在需要V0 的所有行时才使用boolean indexing

    print (df[df.V == 0])
        C  ID  V  YEAR
    0   0   1  0  2011
    3  33   2  0  2013
    5  55   3  0  2014
    

    但如果需要返回至少一个列V 的值等于0 的所有组,添加any,因为filter 需要TrueFalse 用于过滤组中的所有行:

    print(df.groupby(['ID']).filter(lambda x: (x['V'] == 0).any())) 
        C  ID  V  YEAR
    0   0   1  0  2011
    1  11   1  1  2012
    2  22   2  1  2012
    3  33   2  0  2013
    4  44   3  1  2013
    5  55   3  0  2014
    

    更好的测试是更改groupby 的列 - 带有2012 的行被过滤掉,因为没有V==0

    print(df.groupby(['YEAR']).filter(lambda x: (x['V'] == 0).any())) 
        C  ID  V  YEAR
    0   0   1  0  2011
    3  33   2  0  2013
    4  44   3  1  2013
    5  55   3  0  2014
    

    如果性能很重要,请使用 GroupBy.transformboolean indexing

    print(df[(df['V'] == 0).groupby(df['YEAR']).transform('any')]) 
       ID  YEAR  V   C
    0   1  2011  0   0
    3   2  2013  0  33
    4   3  2013  1  44
    5   3  2014  0  55
    

    详情

    print((df['V'] == 0).groupby(df['YEAR']).transform('any')) 
    0     True
    1    False
    2    False
    3     True
    4     True
    5     True
    Name: V, dtype: bool
    

    【讨论】:

    • 你能参考这个创建新问题吗?您是否认为组中至少有一个值是 V 和另一个数据框 df = pd.DataFrame({'ID':[1,2,3], 'V': [0,1,0]) 的值?如果将其更改为 df = pd.DataFrame({'ID':[1,2,3], 'V': [0,1,2]) 它不会返回最后一组所以输出是 {'V': [0, 1, 1, 0], 'ID': [1, 1, 2, 2], 'C': [0, 11, 22, 33], 'YEAR': [2011, 2012, 2012, 2013]}?
    • @jezrael 如果我有 2 个字符串要检查 print(df.groupby(['YEAR']).filter(lambda x: (x['V'] == "abc" or x['V'] == "xyz").any()))
    • 我认为你需要| instaed or(比较数组)并添加parenthesses - print(df.groupby(['YEAR']).filter(lambda x: ((x['V'] == 0) | (x['V'] == 1)).any()))
    • 另一种解决方案print(df.groupby(['YEAR']).filter(lambda x: (x['V'] == 0).any() or (x['V'] == 1)).any())(不确定输出是否相同),但这里将标量与or进行比较
    • 我试过dfnew = df.groupby('OrderID').filter(lambda x: ((x['ResponseType']=='MODIFY_ORDER_REJECT') | x['ResponseType']=='CANCEL_ORDER_REJECT')).any() ) 基本上我的意图是删除所有包含 MODIFY_ORDER_REJECT 或 CANCEL_ORDER_REJECT 的 OrderID 在 csv 中的任何位置。也许可以聊一分钟。谢谢
    猜你喜欢
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    • 2017-05-18
    • 2016-10-22
    • 2021-06-16
    • 2013-10-24
    • 2013-06-06
    • 2019-01-18
    相关资源
    最近更新 更多