如何用Pandas基于原始数据为新增列赋值及实现特征编码
解决方案:将BSXSYMNO映射为症状列的二进制标记
先明确你的核心需求:
- 数据集内同一RID下存在不同VISCODE2分类
- 需要基于
BSXSYMNO的编码(对应ph_dict中的症状名称),把对应症状列设为1,剩余29个症状列设为0 - 目前29个症状列(从
AXNAUSEA到AXSPECIF)为空,需要填充0/1标记
原代码的问题
你的现有代码存在几个关键问题,导致无法达到预期效果:
- 列名引用错误:
df2.loc[index,df2[ph_dict[num]]]的第二个参数应该直接传入症状列的名称字符串(即ph_dict[num]),而不是df2[ph_dict[num]](这会返回一个Series对象,不是合法的列索引) - 处理范围不全:
ph_dict包含1-29的编码,但你只处理了0<num<=20,漏掉了21-29的症状类型 - 初始化缺失:没有先将所有症状列初始化为0,直接赋值1会导致未被赋值的列保持空值,而非预期的0
- 效率问题:
iterrows()在处理大数据集时速度较慢,推荐用更高效的向量化操作替代
修正后的代码方案
方案1:修正循环逻辑(适合小数据集)
# 先初始化所有症状列为0 symptom_cols = list(ph_dict.values()) df2[symptom_cols] = 0 # 遍历每一行完成赋值 for index, row in df2.iterrows(): num = row['BSXSYMNO'] # 检查num是否在ph_dict的有效键范围内 if num in ph_dict: col_name = ph_dict[num] df2.loc[index, col_name] = 1
方案2:向量化操作(高效适配大数据集)
如果你的数据集规模较大,推荐用pd.get_dummies实现无循环的快速处理:
# 将BSXSYMNO编码映射为对应的症状名称 df2['symptom'] = df2['BSXSYMNO'].map(ph_dict) # 生成二进制dummy列,自动将对应症状设为1,其余为0 dummy_df = pd.get_dummies(df2['symptom']) # 确保所有29个症状列都存在(避免某些症状未出现导致列缺失) for col in ph_dict.values(): if col not in dummy_df.columns: dummy_df[col] = 0 # 将dummy列合并回原数据集 df2 = pd.concat([df2, dummy_df], axis=1) # 可选:删除临时生成的symptom列 df2.drop('symptom', axis=1, inplace=True)
分组场景补充(同一RID+VISCODE2多症状)
如果你的需求是同一RID+VISCODE2分组下,所有出现过的BSXSYMNO对应的列都设为1(即一个分组可能对应多个症状),可以按分组处理:
# 初始化症状列为0 symptom_cols = list(ph_dict.values()) df2[symptom_cols] = 0 # 按RID和VISCODE2分组,批量处理每个分组的症状标记 for (rid, viscode), group in df2.groupby(['RID', 'VISCODE2']): # 获取分组内所有有效的BSXSYMNO valid_nums = group['BSXSYMNO'].dropna().unique() for num in valid_nums: if num in ph_dict: col_name = ph_dict[num] df2.loc[group.index, col_name] = 1
以上方案可以完美实现你想要的效果:每个记录对应的症状列设为1,其余列设为0,同时覆盖所有29个症状的处理场景。
内容的提问来源于stack exchange,提问作者weiboo pan
相关产品推荐
相关产品推荐

