如何在Python中计算样本权重以匹配人口特征比例?
问题描述
现有如下样本DataFrame:
import pandas as pd dt = pd.DataFrame({'Age': [20,30,40], 'Gender': ['M', 'F', 'F'], 'Origin': ['Caucasian', 'Asian', 'Latino']})
需要为其添加Weight列,满足以下三个分组求和要求:
- 按
Gender分组求和:M总和为1,F总和为1(对应总体性别比例1:1) - 按
Age分组求和:20总和为1,30总和为2,40总和为3(对应总体年龄比例1:2:3) - 按
Origin分组求和:Caucasian总和为1,Asian总和为4,Latino总和为2(对应总体族裔比例1:4:2)
解决方案
首先需要明确:你提出的三个约束条件存在内在冲突(比如单独满足年龄约束时,性别分组的总和会远超要求值),因此无法找到完全精确满足所有条件的权重。此时可以使用耙样法(Raking)——这是调查抽样中常用的多维度权重校准方法,通过迭代调整权重,让各分组的权重和尽可能逼近目标值。
以下是具体实现代码:
import pandas as pd import numpy as np # 初始化样本数据 dt = pd.DataFrame({'Age': [20,30,40], 'Gender': ['M', 'F', 'F'], 'Origin': ['Caucasian', 'Asian', 'Latino']}) # 定义各特征的目标总和字典 targets = { 'Gender': {'M': 1, 'F': 1}, 'Age': {20: 1, 30: 2, 40: 3}, 'Origin': {'Caucasian': 1, 'Asian': 4, 'Latino': 2} } # 初始化权重为1 dt['Weight'] = 1.0 # 迭代耙样调整,直到收敛 max_iter = 100 tolerance = 1e-6 for _ in range(max_iter): prev_weights = dt['Weight'].copy() # 按每个特征维度调整权重 for col, target in targets.items(): # 计算当前分组的权重和 group_sums = dt.groupby(col)['Weight'].sum() # 计算调整因子 factors = pd.Series(target).reindex(group_sums.index) / group_sums # 应用调整因子到每个样本 dt['Weight'] *= dt[col].map(factors) # 检查收敛:权重变化小于阈值则停止 if np.max(np.abs(dt['Weight'] - prev_weights)) < tolerance: break # 查看调整后的结果 print("带权重的样本数据:") print(dt) # 验证各分组求和结果 print("\nGender分组权重和:") print(dt.groupby('Gender')['Weight'].sum()) print("\nAge分组权重和:") print(dt.groupby('Age')['Weight'].sum()) print("\nOrigin分组权重和:") print(dt.groupby('Origin')['Weight'].sum())
说明
- 耙样法通过循环遍历每个特征维度,不断调整权重因子,逐步让各分组的权重和逼近目标值,最终收敛到一个近似满足所有约束的解
- 你可以根据需求调整迭代次数
max_iter和误差阈值tolerance,阈值越小,结果越接近目标值 - 由于原始约束存在冲突,最终结果无法完全精确匹配所有目标,但误差会控制在极小范围内
内容的提问来源于stack exchange,提问作者quant
相关产品推荐
相关产品推荐

