基于原数据集,如何高效生成DataFrame的NaN行逆映射结果?
我有一个包含若干数值的原始DataFrame df0,基于它得到了第二个DataFrame df1(部分原始值被替换为NaN)。需要生成目标DataFrame df2,使其与df1的NaN行呈逆映射关系:df1中为NaN的行取df0的原始值,非NaN的行则设为NaN。
示例代码:
import pandas as pd df0 = pd.DataFrame({'col1': [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]}) df1 = pd.DataFrame({'col1': [1,2,None,4,5,6,None,8,None,10,11,None,13,None,None]})
期望输出:
df2 = pd.DataFrame({'col1': [None,None,3,None,None,None,7,None,9,None,None,12,None,14,15]})
针对大规模数据集,实现该需求的最优方法是什么?
针对大规模数据集,必须优先选择Pandas原生向量化操作(避免Python循环,利用底层C优化),以下是几种高效方法,性能基本一致,按代码简洁度排序:
1. 利用where方法(首选)
DataFrame.where()方法可直接根据布尔掩码保留/替换值,完全匹配需求:当df1对应位置为NaN时,保留df0的值;否则设为NaN。
df2 = df0.where(df1.isna())
原理:df1.isna()生成布尔掩码,where()在掩码为True的位置保留df0的值,掩码为False的位置自动填充NaN。该方法是纯向量化操作,代码最简洁,底层优化程度最高,处理超大规模数据时性能最优。
2. 利用mask方法(反向逻辑)
DataFrame.mask()是where的反向操作:当条件为True时替换值。这里用df1.notna()作为条件,将df1非NaN的位置替换为NaN,保留df0的其他值:
df2 = df0.mask(df1.notna())
效果与方法1完全一致,性能相当,仅逻辑表述不同,可根据个人习惯选择。
3. 布尔索引赋值
如果需要分步操作,也可以用布尔索引直接赋值:
# 初始化空DataFrame,保持与df0相同的索引和列 df2 = pd.DataFrame(index=df0.index, columns=df0.columns) # 生成掩码:df1中为NaN的位置 mask = df1.isna() # 赋值:仅在掩码为True的位置填充df0的值 df2[mask] = df0[mask]
该方法同样是向量化操作,性能接近前两种,适合需要中间步骤的场景。
以上三种方法均避免了Python层面的循环遍历,处理百万级、千万级数据时,速度比逐行循环快100~1000倍。其中where和mask方法代码最简洁,是大规模数据集的首选方案。
内容的提问来源于stack exchange,提问作者Bas R

