Pandas 中作为列的加权平均值

Weighted Mean as a Column in Pandas

我正在尝试添加一个具有 4 列权重的 4 列的加权平均值的列

df = pd.DataFrame.from_dict(dict([('A', [2000, 1000, 2509, 2145]),
                                  ('A_Weight', [37, 47, 33, 16]),
                                  ('B', [2100, 1500, 2000, 1600]),
                                  ('B_weights', [17, 21, 6, 2]),
                                  ('C', [2500, 1400, 0, 2300]),
                                  ('C_weights', [5, 35, 0, 40]),
                                  ('D', [0, 1600, 2100, 2000]),
                                  ('D_weights', [0, 32, 10, 5])]))

我希望加权平均值位于名为“WA”的新列中,但每次尝试时它都显示 NaN

所需的数据框将是一个新列,其值如下:

我用的公式(((A * A_weight)+(B * b_weight)+(C * C_weight)+(D * D_weight)) / sum(all weights)

df['WA'] = [2071.19,1323.70, 2363.20,2214.60 ]

谢谢

一个简单直接的方法如下:

(由于您的权重列名称的命名不一致,例如一些带有 's' 一些没有,一些带有大写 'W' 一些带有小写 'w',它不方便对列进行分组,例如 .filter())

df['WA'] = ( (df['A'] * df['A_Weight']) + (df['B'] * df['B_weights']) + (df['C'] * df['C_weights']) + (df['D'] * df['D_weights']) ) / (df['A_Weight'] + df['B_weights'] + df['C_weights'] + df['D_weights'])

结果:

print(df)


      A  A_Weight     B  B_weights     C  C_weights     D  D_weights           WA
0  2000        37  2100         17  2500          5     0          0  2071.186441
1  1000        47  1500         21  1400         35  1600         32  1323.703704
2  2509        33  2000          6     0          0  2100         10  2363.204082
3  2145        16  1600          2  2300         40  2000          5  2214.603175

不太直接的方式:

  1. 通过 str.split
  2. 按前缀对列进行分组
  3. 通过groupby prod
  4. 获取列乘积
  5. 获取轴 1 上 sum 乘积的行总和。
  6. filter + sum 在轴 1 上得到“权重”列的总和
  7. 将组积总和除以权重总和。
df['WA'] = (
        df.groupby(df.columns.str.split('_').str[0], axis=1).prod().sum(axis=1)
        / df.filter(regex='_[wW]eight(s)?$').sum(axis=1)
)
      A  A_Weight     B  B_weights     C  C_weights     D  D_weights           WA
0  2000        37  2100         17  2500          5     0          0  2071.186441
1  1000        47  1500         21  1400         35  1600         32  1323.703704
2  2509        33  2000          6     0          0  2100         10  2363.204082
3  2145        16  1600          2  2300         40  2000          5  2214.603175

旧问题的另一种选择:

将数据拆分为分子和分母:

numerator = df.filter(regex=r"[A-Z]$")
denominator = df.filter(like='_')

denominator转换成MultiIndex,用numerator计算时派上用场:

denominator.columns = denominator.columns.str.split('_', expand = True)

numerator乘以denominator,并将结果的总和除以denominator的总和:

outcome = numerator.mul(denominator, level=0, axis=1).sum(1)
outcome = outcome.div(denominator.sum(1))
df.assign(WA = outcome)

      A  A_Weight     B  B_weights     C  C_weights     D  D_weights           WA
0  2000        37  2100         17  2500          5     0          0  2071.186441
1  1000        47  1500         21  1400         35  1600         32  1323.703704
2  2509        33  2000          6     0          0  2100         10  2363.204082
3  2145        16  1600          2  2300         40  2000          5  2214.603175