如何在Pandas DataFrame中校验地点有效性并生成新列?
问题描述
现有主DataFrame如下:
ID Country Employee Location 1 AE Jay AAA 2 AE Mary aa 3 AE Peter bbb 3 AE Peter ddd 6 DK Donk ddd 7 CZ Cesar fff 7 CZ Cesar GGg 7 CZ Cesar 8 CZ Carlos #
以及参考用的lookup DataFrame:
Country Location AE bbb AE aaa AE ccc DK ddd DK eee DK fff CZ ggg CZ hhh
需要根据lookup表按国家校验Location值的有效性,生成名为Legacy Location Name的新列,规则如下:
- 若Location值(不区分大小写)匹配lookup表中对应国家的地点,新列填
CORRECT VALUE; - 若Location值无效,新列保留原Location值,同时将原Location列替换为对应国家在lookup表中的首个地点值;
- 若Location值为空,新列填
LOCATION NOT PROVIDED,同时将原Location列替换为对应国家在lookup表中的首个地点值。
期望输出如下:
ID Country Employee Location Legacy Location 1 AE Jay AAA CORRECT VALUE 2 AE Mary bbb aa 3 AE Peter bbb CORRECT VALUE 3 AE Peter bbb ddd 6 DK Donk ddd CORRECT VALUE 7 CZ Cesar ggg fff 7 CZ Cesar GGg CORRECT VALUE 7 CZ Cesar LOCATION NOT PROVIDED 8 CZ Carlos ggg #
请问实现该需求的最优方法是什么?
最优实现方案(基于Pandas)
通过以下步骤可高效实现需求,核心利用Pandas的分组、映射和条件判断能力,兼顾逻辑清晰与执行效率:
1. 预处理Lookup表
先从Lookup表中提取两个关键映射:
- 每个国家的首个地点值,用于后续替换无效/空的Location;
- 每个国家的有效地点集合(统一转小写),用于快速校验Location的有效性。
2. 分场景处理主DataFrame
按照空值、有效匹配、无效值三个场景分别处理,避免嵌套判断,逻辑更清晰。
具体代码如下:
import pandas as pd # 初始化主DataFrame main_df = pd.DataFrame({ 'ID': [1,2,3,3,6,7,7,7,8], 'Country': ['AE','AE','AE','AE','DK','CZ','CZ','CZ','CZ'], 'Employee': ['Jay','Mary','Peter','Peter','Donk','Cesar','Cesar','Cesar','Carlos'], 'Location': ['AAA','aa','bbb','ddd','ddd','fff','GGg','','#'] }) # 初始化lookup DataFrame lookup_df = pd.DataFrame({ 'Country': ['AE','AE','AE','DK','DK','DK','CZ','CZ'], 'Location': ['bbb','aaa','ccc','ddd','eee','fff','ggg','hhh'] }) # 生成每个国家的首个地点映射字典 country_first_loc = lookup_df.groupby('Country')['Location'].first().to_dict() # 生成每个国家的有效地点小写集合 country_valid_locs = lookup_df.groupby('Country')['Location'].apply(lambda x: set(x.str.lower())).to_dict() # 初始化Legacy列,默认保留原Location值 main_df['Legacy Location Name'] = main_df['Location'] # 处理空值场景 mask_empty = main_df['Location'].str.strip().eq('') main_df.loc[mask_empty, 'Legacy Location Name'] = 'LOCATION NOT PROVIDED' main_df.loc[mask_empty, 'Location'] = main_df.loc[mask_empty, 'Country'].map(country_first_loc) # 处理有效匹配场景 mask_valid = main_df.apply( lambda row: row['Location'].strip().lower() in country_valid_locs.get(row['Country'], set()), axis=1 ) main_df.loc[mask_valid, 'Legacy Location Name'] = 'CORRECT VALUE' # 处理无效值场景:替换Location为对应国家的首个地点 mask_invalid = ~mask_valid & ~mask_empty main_df.loc[mask_invalid, 'Location'] = main_df.loc[mask_invalid, 'Country'].map(country_first_loc) # 输出结果 print(main_df)
方案优势
- 效率优先:使用集合进行有效性校验(查询时间复杂度O(1)),搭配Pandas矢量化操作替代逐行循环,大数据量场景下性能更优;
- 逻辑清晰:分三个独立掩码处理不同场景,代码可读性强,便于维护和修改;
- 扩展性好:后续若规则调整,只需对应修改掩码条件或映射逻辑即可。
内容的提问来源于stack exchange,提问作者Paulo Cortez
相关产品推荐
相关产品推荐

