【问题标题】:How to use groupby transform across columns using method chaining?如何使用方法链接跨列使用 groupby 转换?
【发布时间】:2021-01-30 20:04:53
【问题描述】:

使用方法链接,我希望在 col_1==0 时使用 col_2 的值创建一个新列。

np.random.seed(1)

df = pd.DataFrame({'group':list('AAABBBCCDDDD'),
              'col_1': [-1,0,1,-1,0,1,0,1,-1,0,1,2],
              'col_2': np.random.randint(0, 10, 12)})

    group   col_1   col_2
0     A       -1      5
1     A        0      8
2     A        1      9
3     B       -1      5
4     B        0      0
5     B        1      0
6     C        0      1
7     C        1      7
8     D       -1      6
9     D        0      9
10    D        1      2
11    D        2      4

期望的输出:

    group   col_1   col_2   new_col
0     A       -1       5      8
1     A        0       8      8
2     A        1       9      8
3     B       -1       5      0
4     B        0       0      0
5     B        1       0      0
6     C        0       1      1
7     C        1       7      1
8     D       -1       6      9
9     D        0       9      9
10    D        1       2      9
11    D        2       4      9

我使用 groupby transform 的方法(我希望它能够正常工作,但显然 transform 只访问单个列):

df.assign(
    new_col = lambda df_: df_.groupby('group').transform(lambda x: x.loc[x.col_1==0].col_2)
)
AttributeError: 'Series' object has no attribute 'col_1'

在写这个问题时想出了这个解决方案,但我想我还是会发布:

df.assign(
    new_col = lambda df_: df_.merge(df.groupby('group')
     .apply(lambda x: x.loc[x.col_1==0].col_2)
     .reset_index().rename(columns={'col_2':'new_col'}), on='group'
    ).new_col
)

有没有更好的办法?

【问题讨论】:

    标签: pandas pandas-groupby transform method-chaining


    【解决方案1】:

    如果不匹配col_1 ==1,则使用Series.where 替换所有col_2 值,然后首先使用GroupBy.first 代替NaN 值:

    df = df.assign(
        new_col = lambda df_: df_['col_2'].where(df_['col_1'] == 0)
                                          .groupby(df_['group']).transform('first')
    )
    print (df)
       group  col_1  col_2  new_col
    0      A     -1      5      8.0
    1      A      0      8      8.0
    2      A      1      9      8.0
    3      B     -1      5      0.0
    4      B      0      0      0.0
    5      B      1      0      0.0
    6      C      0      1      1.0
    7      C      1      7      1.0
    8      D     -1      6      9.0
    9      D      0      9      9.0
    10     D      1      2      9.0
    11     D      2      4      9.0
    

    另一种解决方案,Series.map 按条件过滤行,DataFrame.set_indexgroup 列索引:

    df = df.assign(
        new_col = lambda df_: df_['group'].map(df_.loc[df_['col_1'] == 0]
                                                  .set_index('group')['col_2'])
    )
    print (df)
       group  col_1  col_2  new_col
    0      A     -1      5        8
    1      A      0      8        8
    2      A      1      9        8
    3      B     -1      5        0
    4      B      0      0        0
    5      B      1      0        0
    6      C      0      1        1
    7      C      1      7        1
    8      D     -1      6        9
    9      D      0      9        9
    10     D      1      2        9
    11     D      2      4        9
    

    【讨论】:

      猜你喜欢
      • 2016-03-10
      • 2022-06-21
      • 2021-02-26
      • 1970-01-01
      • 2022-06-21
      • 1970-01-01
      • 2021-11-14
      • 1970-01-01
      • 2017-07-02
      相关资源
      最近更新 更多