如何按条件为Pandas DataFrame按不同权重生成随机列值
按条件权重生成DataFrame就业状态列的实现方案
之前实现失败核心有两个原因:一是布尔条件判断没加括号,位运算符优先级高于比较运算符导致筛选逻辑失效;二是没有按分组批量生成对应权重的随机值。
直接用下面的代码即可实现需求,全程保留随机特性,不设固定随机种子时每次运行结果都不一样:
import pandas as pd import random # 基础人口特征生成 weight_sex = [0.55, 0.45] options_sex = [0, 1] # 0 = 男性, 1 = 女性 weight_educ = [0.6, 26.8, 23.6, 23.6, 24.1, 1.3] options_educ = [0, 1, 2, 3, 4, 5] # 0 = 无学历, 5 = 本科及以上 sex = pd.Series(random.choices(options_sex, weights=weight_sex, k=100), name='sex') education = pd.Series(random.choices(options_educ, weights=weight_educ, k=100), name='education') people = pd.concat([sex, education], axis=1) # 就业状态参数配置 option_work = [0, 1, 2] # 0 = 失业, 1 = 非正规就业, 2 = 正规就业 weight_work_educated_man = [0.2, 0.3, 0.5] weight_work_other_people = [0.3, 0.4, 0.3] # 构造高学历男性分组掩码,注意每个判断条件必须单独加括号 mask_educated_male = (people['sex'] == 0) & (people['education'] > 3) # 先生成全量普通人群的就业状态 people['work_status'] = random.choices( option_work, weights=weight_work_other_people, k=len(people) ) # 替换高学历男性组的就业状态为对应权重的随机值 people.loc[mask_educated_male, 'work_status'] = random.choices( option_work, weights=weight_work_educated_man, k=mask_educated_male.sum() )
关键注意点
- 布尔索引的语法坑:pandas中
&(按位与)、|(按位或)的运算优先级高于==、>这类比较运算符,如果不给每个单独的判断条件加括号,代码会先计算0 & people['education']再做相等判断,完全偏离预期逻辑。 - 随机性保证:所有抽样都使用
random.choices做带权重的有放回抽样,只要不手动设置random.seed()固定随机种子,每次运行生成的数据集都会符合设定的人群比例,同时单样本取值随机,不会出现固定结果。 - 性能说明:采用全量生成+局部分组替换的向量化实现,没有用逐行
apply循环,哪怕样本量扩大到十万、百万级也能快速运行。
如果需要验证生成结果的分布是否符合权重要求,可以运行下面的代码做分组统计:
# 统计高学历男性就业分布 print(people[mask_educated_male]['work_status'].value_counts(normalize=True).sort_index()) # 统计其余人群就业分布 print(people[~mask_educated_male]['work_status'].value_counts(normalize=True).sort_index())
内容的提问来源于stack exchange,提问作者Alvaricoque
相关产品推荐
相关产品推荐

