【问题标题】:group and filter pandas dataframe分组和过滤熊猫数据框
【发布时间】:2017-11-30 10:57:35
【问题描述】:
OID,TYPE,ResponseType
100,mod,ok
100,mod,ok
101,mod,ok
101,mod,ok
101,mod,ok
101,mod,ok
101,mod,no
102,mod,ok
102,mod,ok2
103,mod,ok
103,mod,no2

我想删除所有响应为 no 或 no2 的 OID。

我试过了:

dfnew = df.groupby('OID').filter(lambda x: ((x['ResponseType']=='no') | x['ResponseType']=='no2')).any() )

但我得到 SyntaxError: invalid syntax

另一种方法是对所有要过滤的 OID 进行set,然后使用它们来过滤 df。df 有 5000000 行!

预期的操作

OID,TYPE,ResponseType
100,mod,ok
100,mod,ok

102,mod,ok
102,mod,ok2

【问题讨论】:

    标签: python pandas dataframe filter


    【解决方案1】:

    您需要添加一个 (~ 用于反转布尔掩码 - 但它真的很慢:

    dfnew = df.groupby('OID').filter(lambda x: ~((x['ResponseType']=='no') | 
                                                 (x['ResponseType']=='no2')).any() )
                                              #here
    
    print (dfnew)
       OID TYPE ResponseType
    0  100  mod           ok
    1  100  mod           ok
    7  102  mod           ok
    8  102  mod          ok2
    

    另一种解决方案,使用boolean indexing 和双倍isin 更快:

    oids = df.loc[df['ResponseType'].isin(['no','no2']), 'OID']
    print (oids)
    6     101
    10    103
    Name: OID, dtype: int64
    
    dfnew = df[~df['OID'].isin(oids)]
    print (dfnew)
       OID TYPE ResponseType
    0  100  mod           ok
    1  100  mod           ok
    7  102  mod           ok
    8  102  mod          ok2
    

    unique 的解决方案有点慢:

    oids = df.loc[df['ResponseType'].isin(['no','no2']), 'OID'].unique()
    print (oids)
    [101 103]
    

    时间安排

    np.random.seed(123)
    N = 1000000
    df = pd.DataFrame({'ResponseType': np.random.choice(['ok','ok2','no2', 'no'], N),
                       'TYPE':['mod'] * N,
                       'OID':np.random.randint(100000, size=N)})
    print (df)
    
    In [285]: %timeit (df[~df['OID'].isin(df.loc[df['ResponseType'].isin(['no','no2']), 'OID'])])
    10 loops, best of 3: 67.2 ms per loop
    
    In [286]: %timeit (df[~df['OID'].isin(df.loc[df['ResponseType'].isin(['no','no2']), 'OID'].unique())])
    10 loops, best of 3: 69.5 ms per loop
    
    #zipa solution
    In [287]: %timeit (df[~df['OID'].isin(df[df['ResponseType'].isin(['no', 'no2'])]['OID'])])
    10 loops, best of 3: 91.5 ms per loop
    
    #groupby solution :(
    In [288]: %timeit (df.groupby('OID').filter(lambda x: ~((x['ResponseType']=='no') |  (x['ResponseType']=='no2')).any() ))
    1 loop, best of 3: 1min 54s per loop
    

    【讨论】:

    • 一旦我过滤掉要消除的 oid,如何从主 df 中删除它们? df[df['OID'] 不在 oids]
    • 我认为boolean indexing - df[~df['OID'].isin(oids)]
    • 谢谢,在这一切过程中,我如何确保订单没有错位。它应该保留原始df的顺序
    • 是的,当然。它创建布尔掩码 - TrueFalse 值并按它过滤。
    【解决方案2】:

    你可以这样做:

    df[~df['OID'].isin(df[df['ResponseType'].isin(['no', 'no2'])]['OID'])]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-25
      • 2014-07-11
      • 2019-01-13
      • 2021-08-20
      • 2019-04-13
      • 2015-05-28
      • 2018-02-06
      • 2018-09-28
      相关资源
      最近更新 更多