使用整洁数据原则,在 Pandas/Python 中实现 Groupby Mutate 的等效方法

3

我的数据框如下所示:

group_var1 = ['A1','A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A2', 'A2', 'A2', 'A2', 'A2', 'A2', 'A2', 'A2']
group_var2 = ['B1', 'B1', 'B1', 'B1', 'B2', 'B2', 'B2', 'B2', 'B1', 'B1', 'B1', 'B1', 'B2', 'B2', 'B2', 'B2']
group_var3 = ['C1', 'C2', 'C1', 'C2', 'C1', 'C2', 'C1', 'C2', 'C1', 'C2', 'C1', 'C2', 'C1', 'C2', 'C1', 'C2']

value = np.arange(len(group_var1))

ex_df = pd.DataFrame({
    'group_var1' : group_var1,
    'group_var2' : group_var2,
    'group_var3' : group_var3,
    'value' : value
})


当调用时,应该产生以下结果:
    group_va1   group_va2   group_va3   value
0   A1  B1  C1  0
1   A1  B1  C2  1
2   A1  B1  C1  2
3   A1  B1  C2  3
4   A1  B2  C1  4
5   A1  B2  C2  5
6   A1  B2  C1  6
7   A1  B2  C2  7
8   A2  B1  C1  8
9   A2  B1  C2  9
10  A2  B1  C1  10
11  A2  B1  C2  11
12  A2  B2  C1  12
13  A2  B2  C2  13
14  A2  B2  C1  14
15  A2  B2  C2  15


我的目标是按列group_var1group_var2group_var3对DataFrame进行分组,然后计算每个组内的平均值value,并将这些结果添加到现有的DataFrame中作为一行mean_ex。在R中,可以通过ex_df %>% group_by(c(group_var1, group_var2, group_var3)) %>% mutate(mean_ex = mean(value))实现,该代码会自动将新的值分配给相应的行。
我已经找到了一种方式来通过将每个组中的所有值聚合到仅平均值 (ex_df.groupby(['group_var1', 'group_var2', 'group_var3']).mean()) 来汇总DataFrame,但我希望平均值成为我的现有DataFrame中的一个新列,而不是小尺寸的df。我的期望输出可以在下面找到,并且是通过在我的原始df和上述不需要的聚合表上使用pd.merge()来实现的。

    group_var1  group_var2  group_var3  value   mean_ex
0   A1  B1  C1  0   1
1   A1  B1  C2  1   2
2   A1  B1  C1  2   1
3   A1  B1  C2  3   2
4   A1  B2  C1  4   5
5   A1  B2  C2  5   6
6   A1  B2  C1  6   5
7   A1  B2  C2  7   6
8   A2  B1  C1  8   9
9   A2  B1  C2  9   10
10  A2  B1  C1  10  9
11  A2  B1  C2  11  10
12  A2  B2  C1  12  13
13  A2  B2  C2  13  14
14  A2  B2  C1  14  13
15  A2  B2  C2  15  14


我的问题是,是否有办法在不创建单独的数据框并将其合并回原始数据框的情况下实现所期望的输出?谢谢。
2个回答

1
您可以像在R中使用datar一样,在Python中实现它:
>>> from datar.all import c, f, tibble, mutate, mean, group_by
>>> 
>>> group_var1 = ['A1','A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A2', 'A2', 'A2', 'A2', 'A2', 'A2', 'A2'
, 'A2']
>>> group_var2 = ['B1', 'B1', 'B1', 'B1', 'B2', 'B2', 'B2', 'B2', 'B1', 'B1', 'B1', 'B1', 'B2', 'B2', 'B2
', 'B2']
>>> group_var3 = ['C1', 'C2', 'C1', 'C2', 'C1', 'C2', 'C1', 'C2', 'C1', 'C2', 'C1', 'C2', 'C1', 'C2', 'C1
', 'C2']
>>> 
>>> df = tibble(
...     group_var1,
...     group_var2,
...     group_var3,
...     value=range(len(group_var1))
... )
>>> 
>>> df >> group_by(
...     f.group_var1, f.group_var2, f.group_var3
... ) >> mutate(
...     mean_ex = mean(f.value)
... )
   group_var1 group_var2 group_var3   value   mean_ex
     <object>   <object>   <object> <int64> <float64>
0          A1         B1         C1       0       1.0
1          A1         B1         C2       1       2.0
2          A1         B1         C1       2       1.0
3          A1         B1         C2       3       2.0
4          A1         B2         C1       4       5.0
5          A1         B2         C2       5       6.0
6          A1         B2         C1       6       5.0
7          A1         B2         C2       7       6.0
8          A2         B1         C1       8       9.0
9          A2         B1         C2       9      10.0
10         A2         B1         C1      10       9.0
11         A2         B1         C2      11      10.0
12         A2         B2         C1      12      13.0
13         A2         B2         C2      13      14.0
14         A2         B2         C1      14      13.0
15         A2         B2         C2      15      14.0

[Groups: group_var1, group_var2, group_var3 (n=8)]

免责声明:我是datar包的作者。


1
使用 transformassign:

ex_df.assign(
    mean_val = 
    ex_df
    .groupby(["group_var1", "group_var2",  "group_var3"])
    .value
    .transform('mean')
)

   group_var1 group_var2 group_var3  value  mean_val
0          A1         B1         C1      0         1
1          A1         B1         C2      1         2
2          A1         B1         C1      2         1
3          A1         B1         C2      3         2
4          A1         B2         C1      4         5
5          A1         B2         C2      5         6
6          A1         B2         C1      6         5
7          A1         B2         C2      7         6
8          A2         B1         C1      8         9
9          A2         B1         C2      9        10
10         A2         B1         C1     10         9
11         A2         B1         C2     11        10
12         A2         B2         C1     12        13
13         A2         B2         C2     13        14
14         A2         B2         C1     14        13
15         A2         B2         C2     15        14
解释
Pandas的assigndplyr::mutate的粗略等价物,而transform会在groupby之前将分组操作广播到输入的所有初始行,而不仅仅是调用聚合函数后的单个值。类似于df.groupby('a').x.mean()这样的操作将导致每个分组索引集上的单个值,这是与dplyr::summarise相对应的模拟。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接