基于匹配条件从MAP DataFrame随机抽取指定数量样本填充df的Leistungsgruppe空值
基于匹配条件从MAP DataFrame随机抽取指定数量样本填充df的Leistungsgruppe空值
嘿,别纠结iterrows啦,Pandas处理这种场景用分组和向量化操作要舒服得多,效率也更高。我给你一步步捋清楚实现思路和代码:
第一步:预处理MAP,每个匹配组随机保留最多3个Leistungsgruppe样本
首先我们要把MAP按照MANDANT、Fachabteilung、FACHEXPERTISE这三个关键字段分组,每个组里如果条目超过3个就随机选3个,少于等于3个就全留,完美贴合你“超过3个就缩到3个”的要求:
import pandas as pd import numpy as np # 你的原始数据 df = pd.DataFrame({'PERSONALNUMMER': {4756: '0209740',4820: '0234212',4855: '0251297',4750: '0209326',4992: '4000404'}, 'MANDANT': {4756: 'OM', 4820: 'OM', 4855: 'OM', 4750: 'OM', 4992: 'OM'}, 'Fachabteilung': {4756: 'HA2300',4820: 'HA2300',4855: 'HA2300',4750: 'HA2300',4992: 'HA2300'}, 'FACHEXPERTISE': {4756: 'AQ10',4820: 'AQ10',4855: 'AQ10',4750: 'AQ10',4992: 'AQ10'}, 'Leistungsgruppe': {4756: pd.NA,4820: 'Endoprothetik Knie',4855: 'Allgemeine Chirurgie',4750: 'Wirbelsaeuleneingriffe',4992: pd.NA}}) MAP = pd.DataFrame({'MANDANT': {238: 'OM', 239: 'OM', 240: 'OM', 241: 'OM'}, 'Fachabteilung': {238: 'HA2300', 239: 'HA2300', 240: 'HA2300', 241: 'HA2300'}, 'FACHEXPERTISE': {238: 'AQ10', 239: 'AQ10', 240: 'AQ10', 241: 'AQ10'}, 'Leistungsgruppe': {238: 'Allgemeine Chirurgie', 239: 'Endoprothetik Huefte',240: 'Endoprothetik Knie',241: 'Revision Huefte'}, 'VK': {238: 3,239: 14,240: 28,241: 22}}) # 预处理MAP:每个分组随机采样最多3条,random_state固定随机结果(可选,方便调试) sampled_map = MAP.groupby(['MANDANT', 'Fachabteilung', 'FACHEXPERTISE']).apply( lambda group: group.sample(n=min(3, len(group)), random_state=42) ).reset_index(drop=True) # 构建「分组键」到「Leistungsgruppe可选列表」的映射字典,方便后续快速查找 group_options = sampled_map.groupby(['MANDANT', 'Fachabteilung', 'FACHEXPERTISE'])['Leistungsgruppe'].apply(list).to_dict()
第二步:填充df里的空值行
接下来写个简单的处理函数,针对每一行判断:如果Leistungsgruppe不为空就直接返回,为空的话就从对应分组的可选列表里随机挑一个填充:
def fill_leistung(row): # 当前值不为空,直接返回原内容 if pd.notna(row['Leistungsgruppe']): return row['Leistungsgruppe'] # 生成当前行的分组匹配键 group_key = (row['MANDANT'], row['Fachabteilung'], row['FACHEXPERTISE']) # 获取该分组的可选Leistungsgruppe列表 options = group_options.get(group_key, []) # 有可选值就随机选一个,没有就保留原空值 return np.random.choice(options) if options else row['Leistungsgruppe'] # 对df的Leistungsgruppe列应用填充逻辑 df['Leistungsgruppe'] = df.apply(fill_leistung, axis=1) # 查看填充后的结果 print(df)
额外说明:
- 这个方案比
iterrows高效多了,尤其是数据量大的时候,Pandas的apply虽然是逐行处理,但内部做了优化,逻辑也更清晰; - 如果需要固定随机结果(比如调试时要复现相同填充结果),可以在调用
np.random.choice前加上np.random.seed(42),或者保持sample里的random_state参数; - 如果某个分组没有匹配到MAP里的内容,会自动保留原空值,不会报错。
备注:内容来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

