使用apply筛选DataFrame相似行返回异常结果,寻求解决方案
问题描述
我的数据集包含UNITID、institution_name、program_name、CIPCODE、type列,示例数据如下:
UNITID : 100654 institution_name : Harvard program_name : Medicine CIPCODE : 52.0203 type : Bachelor's
需求:针对原数据集中特定UNITID对应的子集data_subset,筛选满足以下条件的相似行:
- CIPCODE前四位数字相同
- CIPCODE剩余数字不同
type字段相同UNITID字段不同
我编写的代码执行后,得到的是包含多个DataFrame(含空DataFrame)的序列,而非预期的单一筛选结果:
# data是原始DataFrame data['CIPCODE'] = data['CIPCODE'].astype(str).str.zfill(7) data['CIPCODE_group'] = data['CIPCODE'].str.replace(".", "").str[:4] data['CIPCODE_decimal'] = data['CIPCODE'].str.replace(".", "").str[4:] def find_similar_programs(row: pd.Series, df: pd.DataFrame): return df[ (df['CIPCODE_group'] == row['CIPCODE_group']) & (df['CIPCODE_decimal'] != row['CIPCODE_decimal']) & (df['type'] == row['type']) & (df['UNITID'] != row['UNITID'])] data_subset=data[data['UNITID']==166027] similar_programs = data_subset.apply(find_similar_programs, df = data, axis = 1)
解决方案
问题原因
apply会对data_subset的每一行单独执行筛选逻辑,返回对应行的匹配结果DataFrame,最终得到的是一个存储多个DataFrame的Series,而非合并后的单一结果集。
方法一:批量筛选(推荐,效率更高)
直接提取data_subset的关键条件,一次性完成筛选,避免逐行遍历:
import pandas as pd # 保留原始CIPCODE处理逻辑 data['CIPCODE'] = data['CIPCODE'].astype(str).str.zfill(7) data['CIPCODE_group'] = data['CIPCODE'].str.replace(".", "").str[:4] data['CIPCODE_decimal'] = data['CIPCODE'].str.replace(".", "").str[4:] # 目标子集 target_unitid = 166027 data_subset = data[data['UNITID'] == target_unitid] # 提取子集的关键匹配条件 # 要匹配的CIPCODE分组和type组合 group_type_pairs = data_subset[['CIPCODE_group', 'type']].drop_duplicates() # 子集里的CIPCODE后缀(需要排除) exclude_decimals = data_subset['CIPCODE_decimal'].unique() # 合并条件筛选相似行 similar_programs = data.merge(group_type_pairs, on=['CIPCODE_group', 'type'], how='inner') similar_programs = similar_programs[ (~similar_programs['CIPCODE_decimal'].isin(exclude_decimals)) & (similar_programs['UNITID'] != target_unitid) ].reset_index(drop=True)
方法二:合并现有结果
如果要保留原有的逐行筛选逻辑,只需将返回的多个DataFrame合并并去重:
# 保留你原有的代码逻辑 data['CIPCODE'] = data['CIPCODE'].astype(str).str.zfill(7) data['CIPCODE_group'] = data['CIPCODE'].str.replace(".", "").str[:4] data['CIPCODE_decimal'] = data['CIPCODE'].str.replace(".", "").str[4:] def find_similar_programs(row: pd.Series, df: pd.DataFrame): return df[ (df['CIPCODE_group'] == row['CIPCODE_group']) & (df['CIPCODE_decimal'] != row['CIPCODE_decimal']) & (df['type'] == row['type']) & (df['UNITID'] != row['UNITID'])] data_subset = data[data['UNITID'] == 166027] similar_programs_series = data_subset.apply(find_similar_programs, df=data, axis=1) # 合并所有非空DataFrame并去重 similar_programs = pd.concat( [df for df in similar_programs_series if not df.empty], ignore_index=True ).drop_duplicates().reset_index(drop=True)
内容的提问来源于stack exchange,提问作者analyst92
相关产品推荐
相关产品推荐

