代码之家  ›  专栏  ›  技术社区  ›  Zmnako Awrahman beloncfy

按列分组,然后根据条件筛选

  •  3
  • Zmnako Awrahman beloncfy  · 技术社区  · 8 年前

    我有一个df,我想根据分组筛选出一个列。我想按组合分组(( cc , odd , tree1 tree2 )如果是第4天,则保留,否则放弃

    df = pd.DataFrame()
    df['cc'] = ['BB', 'BB', 'BB', 'BB','BB', 'BB','BB', 'BB', 'DD', 'DD', 'DD', 'DD', 'DD', 'DD', 'DD', 'DD', 'ZZ', 'ZZ', 'ZZ', 'ZZ', 'ZZ', 'ZZ', 'ZZ', 'ZZ']
    df['odd'] = [3434, 3434, 3434, 3434, 3435, 3435, 3435, 3435, 3434, 3434, 3434, 3434, 3435, 3435, 3435, 3435, 3434, 3434, 3434, 3434, 3435, 3435, 3435, 3435]
    df['tree1'] = ['ASP', 'ASP', 'ASP', 'ASP', 'SAP', 'SAP', 'SAP', 'SAP', 'ASP', 'ASP', 'ASP', 'ASP', 'SAP', 'SAP', 'SAP', 'SAP', 'ASP', 'ASP', 'ASP', 'ASP', 'SAP', 'SAP', 'SAP', 'SAP']
    df['tree2'] = ['ATK', 'ATK','ATK','ATK','ATK','ATK','ATK','ATK', 'ATK', 'ATK','ATK','ATK','ATK','ATK','ATK','ATK', 'ATK', 'ATK','ATK','ATK','ATK','ATK','ATK','ATK']
    df['day'] = [1, 2, 3, 4, 3, 4, 5, 6, 2, 3, 4, 5, 1, 3, 5, 7, 1, 2, 6, 8, 2, 4, 6, 8]
    df
    

    我试过了,但这会删除日值小于4的任何行

    df_grouped = df.groupby(['cc', 'odd', 'tree1', 'tree2']).filter(df['day'] > 4)
    

    我知道这个错误 TypeError: 'Series' object is not callable

    试过这个

    df_grouped = df.groupby(['cc', 'odd', 'tree1', 'tree2']).filter(lambda x: x['day'] > 4)
    

    我知道这个错误 TypeError: filter function returned a Series, but expected a scalar bool .

    我寻找并试图解决这些错误,但提出的解决方案对我不起作用。我想得到如下df:

    df1 = pd.DataFrame()
    df1['cc'] = ['BB', 'BB','BB', 'BB', 'DD', 'DD', 'DD', 'DD', 'DD', 'DD', 'DD', 'DD', 'ZZ', 'ZZ', 'ZZ', 'ZZ', 'ZZ', 'ZZ', 'ZZ', 'ZZ']
    df1['odd'] = [3435, 3435, 3435, 3435, 3434, 3434, 3434, 3434, 3435, 3435, 3435, 3435, 3434, 3434, 3434, 3434, 3435, 3435, 3435, 3435]
    df1['tree1'] = ['SAP', 'SAP', 'SAP', 'SAP', 'ASP', 'ASP', 'ASP', 'ASP', 'SAP', 'SAP', 'SAP', 'SAP', 'ASP', 'ASP', 'ASP', 'ASP', 'SAP', 'SAP', 'SAP', 'SAP']
    df1['tree2'] = ['ATK','ATK','ATK','ATK', 'ATK', 'ATK','ATK','ATK','ATK','ATK','ATK','ATK', 'ATK', 'ATK','ATK','ATK','ATK','ATK','ATK','ATK']
    df1['day'] = [3, 4, 5, 6, 2, 3, 4, 5, 1, 3, 5, 7, 1, 2, 6, 8, 2, 4, 6, 8]
    df1
    

    我试着用 any 但我做不到,它只会回来 True False 而不是筛选数据帧。

    2 回复  |  直到 8 年前
        1
  •  3
  •   cs95 abhishek58g    8 年前

    既然我明白了你的意思,我们试试 transform + any :

    df[df.assign(key=df.day > 4)
         .groupby(['cc', 'odd', 'tree1', 'tree2']).key.transform('any')
    ]
    

    或者,

    df[df.day.gt(4).groupby([df.cc, df.odd, df.tree1, df.tree2]).transform('any')]
    

        cc   odd tree1 tree2  day
    4   BB  3435   SAP   ATK    3
    5   BB  3435   SAP   ATK    4
    6   BB  3435   SAP   ATK    5
    7   BB  3435   SAP   ATK    6
    8   DD  3434   ASP   ATK    2
    9   DD  3434   ASP   ATK    3
    10  DD  3434   ASP   ATK    4
    11  DD  3434   ASP   ATK    5
    12  DD  3435   SAP   ATK    1
    13  DD  3435   SAP   ATK    3
    14  DD  3435   SAP   ATK    5
    15  DD  3435   SAP   ATK    7
    16  ZZ  3434   ASP   ATK    1
    17  ZZ  3434   ASP   ATK    2
    18  ZZ  3434   ASP   ATK    6
    19  ZZ  3434   ASP   ATK    8
    20  ZZ  3435   SAP   ATK    2
    21  ZZ  3435   SAP   ATK    4
    22  ZZ  3435   SAP   ATK    6
    23  ZZ  3435   SAP   ATK    8
    
        2
  •  2
  •   EdChum Arthur G    8 年前

    你想要的是:

    In[116]:
    df_grouped = df.groupby(['cc', 'odd', 'tree1', 'tree2']).filter(lambda x: (x['day'] > 4).any())
    df_grouped
    
    Out[116]: 
        cc   odd tree1 tree2  day
    4   BB  3435   SAP   ATK    3
    5   BB  3435   SAP   ATK    4
    6   BB  3435   SAP   ATK    5
    7   BB  3435   SAP   ATK    6
    8   DD  3434   ASP   ATK    2
    9   DD  3434   ASP   ATK    3
    10  DD  3434   ASP   ATK    4
    11  DD  3434   ASP   ATK    5
    12  DD  3435   SAP   ATK    1
    13  DD  3435   SAP   ATK    3
    14  DD  3435   SAP   ATK    5
    15  DD  3435   SAP   ATK    7
    16  ZZ  3434   ASP   ATK    1
    17  ZZ  3434   ASP   ATK    2
    18  ZZ  3434   ASP   ATK    6
    19  ZZ  3434   ASP   ATK    8
    20  ZZ  3435   SAP   ATK    2
    21  ZZ  3435   SAP   ATK    4
    22  ZZ  3435   SAP   ATK    6
    23  ZZ  3435   SAP   ATK    8
    

    所以这将过滤掉组中没有 'day' 值大于4

    计时 :

    %timeit df[df.day.gt(4).groupby([df.cc, df.odd, df.tree1, df.tree2]).transform('any')]
    %timeit df.groupby(['cc', 'odd', 'tree1', 'tree2']).filter(lambda x: (x['day'] > 4).any())
    %timeit df[df.assign(key=df.day > 4).groupby(['cc', 'odd', 'tree1', 'tree2']).key.transform('any')]
    100 loops, best of 3: 5.9 ms per loop
    100 loops, best of 3: 5.42 ms per loop
    100 loops, best of 3: 3.62 ms per loop
    

    所以@coldspeed的第一个方法是这里最快的