Pandas筛选两DataFrame独有GN行、标注非共有值来源及代码优化
实现方法与代码优化
现有代码可优化点
你当前的实现逻辑是正确的,但存在两处不必要的性能损耗:
- 不需要将
GN列转换为Python原生列表,pandas.Series.isin()方法原生支持传入Series对象做匹配,省去列表转换的开销 - 不需要用列表推导式过滤空值,
notna()方法是pandas内置的向量化操作,执行效率远高于Python层的列表循环,且isin()对空值的匹配默认返回False,不会造成空值误判
优化后的基础实现(保留原有输出结构)
优化后代码无需做列表转换,执行速度在大数据量下会有明显提升:
import pandas as pd sdf = pd.read_excel(r"C:\Users\fnafee\Desktop\DiffExp\Results\smokersfilteredreal.xlsx") nsdf = pd.read_excel(r"C:\Users\fnafee\Desktop\DiffExp\Results\nonsmokersfilteredreal.xlsx") # 提前过滤GN列为空的无效行 sdf_valid = sdf[sdf['GN'].notna()].copy() nsdf_valid = nsdf[nsdf['GN'].notna()].copy() # 直接匹配对方数据集的GN列,筛选独有行 unique_S = sdf_valid[~sdf_valid['GN'].isin(nsdf_valid['GN'])] unique_NS = nsdf_valid[~nsdf_valid['GN'].isin(sdf_valid['GN'])]
带来源标注的对称差集实现
你提到的symmetric_difference()只能返回差集值本身,无法标注来源。如果需要统一输出两个列表/数据集的互不共有值、同时标记所属来源,可以直接用pandas的merge函数搭配indicator参数一步实现:
# 为两个数据集添加来源标记 sdf_valid['source'] = 'smokers' nsdf_valid['source'] = 'nonsmokers' # 外连接合并,自动生成_merge列标记行来源 merged_df = pd.merge( sdf_valid, nsdf_valid, on='GN', how='outer', indicator=True ) # 过滤出仅在单边存在的独有值行 all_unique_rows = merged_df[merged_df['_merge'] != 'both'].copy()
生成的_merge列取值含义如下:
left_only:当前GN值仅存在于吸烟者数据集(sdf)right_only:当前GN值仅存在于非吸烟者数据集(nsdf)both:两个数据集共有,已被过滤
如果需要拆分回两个单独的独有行表,直接按_merge列筛选即可,和之前的unique_S、unique_NS输出完全一致。
内容的提问来源于stack exchange,提问作者Farzeen Nafees
相关产品推荐
相关产品推荐

