Python 如何将分组结果广播到所有行?

Python 如何将分组结果广播到所有行?,python,pandas,pandas-groupby,Python,Pandas,Pandas Groupby,使用Pandas 1.0.1,鉴于此演示数据帧,我想用在子组“框”上计算的中值替换数字列权重和价格(不修改原始数据帧): 实际: df.groupby('box')[['weight', 'price']].transform(lambda x: np.median(x)) weight price 0 2.00 2.10 1 2.00 2.10 2 2.00 2.10 3 3.50 2.40 4 3.50 2.40 5 5.25

使用Pandas 1.0.1,鉴于此演示数据帧,我想用在子组“框”上计算的中值替换数字列权重和价格(不修改原始数据帧):

实际:

df.groupby('box')[['weight', 'price']].transform(lambda x: np.median(x))
   weight  price
0    2.00   2.10
1    2.00   2.10
2    2.00   2.10
3    3.50   2.40
4    3.50   2.40
5    5.25   3.25
6    5.25   3.25
7    5.25   3.25
8    5.25   3.25
预期:

    box id_in_box  weight  price
0  a100        2x     2.00   2.10
1  a100        1x     2.00   2.10
2  a100        3x     2.00   2.10
3  a200        2x     3.50   2.40
4  a200        1x     3.50   2.40
5  a300        3x     5.25   3.25
6  a300        1x     5.25   3.25
7  a300        2x     5.25   3.25
8  a300        4x     5.25   3.25

如何以最有效的方式实现这一点?

您需要以某种方式组合这两种输出(如评论中所述)。复制工作(如您所建议),但需要2行代码:

df_new = df.copy()
df_new[['weight', 'price']] = df_new.groupby('box')[['weight', 'price']].transform(lambda x: np.median(x))
不覆盖原始数据帧的单行解决方案是通过join实现的,尽管对于大数据来说效率不高:

df_new = pd.merge(
    left=df[['box', 'id_in_box']],
    right=df.groupby('box')[['weight', 'price']].median(),
    left_on='box',
    right_index=True
)
结果:

    box id_in_box  weight  price
0  a100        2x    2.00   2.10
1  a100        1x    2.00   2.10
2  a100        3x    2.00   2.10
3  a200        2x    3.50   2.40
4  a200        1x    3.50   2.40
5  a300        3x    5.25   3.25
6  a300        1x    5.25   3.25
7  a300        2x    5.25   3.25
8  a300        4x    5.25   3.25

这是一种原始的方法

gb = df.groupby(['box'])['weight'].transform(lambda x: np.median(x))
gb1 = df.groupby(['box'])['price'].transform(lambda x: np.median(x))

df['weight'] = gb
df['price'] = gb1

我不想修改原始数据帧。是否需要在运行分组操作之前创建副本,然后将结果分配给此副本?这是产生这个结果的唯一方法吗?
    box id_in_box  weight  price
0  a100        2x    2.00   2.10
1  a100        1x    2.00   2.10
2  a100        3x    2.00   2.10
3  a200        2x    3.50   2.40
4  a200        1x    3.50   2.40
5  a300        3x    5.25   3.25
6  a300        1x    5.25   3.25
7  a300        2x    5.25   3.25
8  a300        4x    5.25   3.25
gb = df.groupby(['box'])['weight'].transform(lambda x: np.median(x))
gb1 = df.groupby(['box'])['price'].transform(lambda x: np.median(x))

df['weight'] = gb
df['price'] = gb1