如何修正代码:将df1非空对应位置的df2值替换为np.nan
问题解决:根据df1非空位置替换df2对应值为NaN
数据与需求
现有两个DataFrame:
df1
ticker A B C date 2022-01-01 NaN NaN 100 2022-01-02 NaN 200 NaN 2022-01-03 100 NaN NaN 2022-01-04 NaN NaN 120
df2
ticker A B C date 2022-01-02 145 233 100 2022-01-03 231 200 241 2022-01-04 100 200 422 2022-01-05 424 324 222 2022-01-06 400 421 320
需求:将df2中与df1非空值对应的索引和列位置的值设为np.nan,得到如下结果:
df3
ticker A B C date 2022-01-02 145 NaN 100 2022-01-03 NaN 200 241 2022-01-04 100 200 NaN 2022-01-05 424 324 222 2022-01-06 400 421 320
错误代码与问题
尝试以下代码时出现报错:
for col in df1.columns: idx = df1[df1[col].notna()].index if df2[col][idx] == df1[col][idx]: df2[col][idx] = np.nan
报错信息:
ValueError: The truth value of a Series is ambiguous. Use a.empty(), a.bool(), a.item(), a.any() or a.all().
错误原因:df2[col][idx] == df1[col][idx]返回的是布尔Series,直接用if判断会触发歧义——Python无法判断你要验证的是Series全为True、任意True还是其他逻辑。此外,你的需求是基于位置而非值匹配,这个if判断本身就是多余的。
解决方案
方法1:向量化操作(推荐,高效简洁)
利用Pandas的向量化特性,直接通过掩码完成赋值:
import pandas as pd import numpy as np # 生成df1的非空掩码,对齐df2的索引和列 mask = df1.notna().reindex_like(df2) # 将df2中掩码为True的位置设为NaN df3 = df2.mask(mask)
方法2:重写循环(若需保留循环逻辑)
复制df2避免修改原数据,处理索引交集后直接赋值:
df3 = df2.copy() for col in df1.columns: # 只保留df2中存在的、df1当前列非空的索引 idx = df1[df1[col].notna()].index.intersection(df3.index) # 定位位置赋值为NaN df3.loc[idx, col] = np.nan
注:如果你的实际需求是当df1与df2对应位置值相等时才替换为NaN,可修改循环为:
df3 = df2.copy() for col in df1.columns: idx = df1[df1[col].notna()].index.intersection(df3.index) # 匹配值相等的位置 match_mask = df3.loc[idx, col] == df1.loc[idx, col] df3.loc[idx[match_mask], col] = np.nan
内容的提问来源于stack exchange,提问作者MathMan 99
相关产品推荐
相关产品推荐

