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
不太直接的方式:
- 通过
str.split
按前缀对列进行分组
- 通过
groupby prod
获取列乘积
- 获取轴 1 上
sum
乘积的行总和。
filter
+ sum
在轴 1 上得到“权重”列的总和
- 将组积总和除以权重总和。
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
我正在尝试添加一个具有 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
不太直接的方式:
- 通过
str.split
按前缀对列进行分组
- 通过
groupby prod
获取列乘积
- 获取轴 1 上
sum
乘积的行总和。 filter
+sum
在轴 1 上得到“权重”列的总和- 将组积总和除以权重总和。
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