如何更简洁地计算Pandas DataFrame每行的加权平均值?
问题:计算Pandas DataFrame每行的加权平均值(更简洁实现)
原始DataFrame数据
代码定义
import pandas as pd data = {'a': [76,65,32,43,43], 'number of a': [4,4,4,3,4], 'b': [75,98,56,90,88], 'number of b' : [7,6,7,2,2], 'c': [54,44,65,76,66], 'number of c': [9,'',1,3,6]} df = pd.DataFrame(data)
表格展示
| a | number of a | b | number of b | c | number of c |
|---|---|---|---|---|---|
| 76 | 4 | 75 | 7 | 54 | 9 |
| 65 | 4 | 98 | 6 | 44 | |
| 32 | 4 | 56 | 7 | 65 | 1 |
| 43 | 3 | 90 | 2 | 76 | 3 |
| 43 | 4 | 88 | 2 | 66 | 6 |
需求说明
需要以number of a、number of b、number of c列为权重,计算a、b、c列的每行加权平均值,已实现以下代码,但寻求更简洁的写法:
df['avg'] = ((df['a'].fillna(0)*df['number of a'].fillna(0)) + (df['b'].fillna(0)*df['number of b'].fillna(0)) + (df['c'].fillna(0)*df['number of c'].fillna(0)))/ (df['number of a'].fillna(0) + df['number of b'].fillna(0) + df['number of c'].fillna(0))
更简洁的实现方法
方法一:批量筛选列,向量化计算
适合列名有规律的场景,无需逐个写列名,自动处理空值:
# 筛选权重列和数值列 weight_cols = [col for col in df.columns if col.startswith('number of')] value_cols = [col for col in df.columns if col in ['a', 'b', 'c']] # 将权重列中的空字符串转为NaN,并转为数值类型 df[weight_cols] = df[weight_cols].apply(pd.to_numeric, errors='coerce') # 计算分子:各数值列与对应权重列相乘后按行求和 numerator = (df[value_cols] * df[weight_cols]).sum(axis=1) # 计算分母:所有权重列按行求和 denominator = df[weight_cols].sum(axis=1) # 计算加权平均值,替换分母为0的情况(避免除以0报错) df['avg'] = numerator / denominator.replace(0, pd.NA)
方法二:用映射关系关联列
通过明确值列与权重列的映射,代码可读性高,易于维护:
# 定义值列和对应权重列的映射 col_pairs = {'a': 'number of a', 'b': 'number of b', 'c': 'number of c'} # 转换权重列为数值型,空字符串转为NaN df[col_pairs.values()] = df[col_pairs.values()].apply(pd.to_numeric, errors='coerce') # 计算分子和分母 numerator = sum(df[val] * df[weight] for val, weight in col_pairs.items()) denominator = sum(df[weight] for weight in col_pairs.values()) # 计算加权平均值 df['avg'] = numerator / denominator.replace(0, pd.NA)
注意点
原始数据中number of c列存在空字符串,需要先转为数值型NaN,否则会导致乘法计算出错,以上两种方法都提前处理了这个问题,比原始代码更严谨。
内容的提问来源于stack exchange,提问作者DouxDoux
相关产品推荐
相关产品推荐

