Pandas透视表新增Intl列后出现大量NaN值问题排查
问题诊断与解决方案
看起来你的问题大概率出在两个容易踩坑的环节:链式索引导致的更新未真正写入原数据,或者去重步骤意外过滤了有效条目,我们一步步拆解排查:
1. 先解决链式索引的隐形陷阱
你用来更新货币列的代码:
datagrouped['List Price Currency'][df['Price Book Name'].str.contains("International",na=False)] = 'Intl'
这是典型的链式索引操作(先取列再做行切片),Pandas通常会触发SettingWithCopyWarning(如果没关闭警告的话)。虽然你打印时看到值更新了,但实际上可能只是修改了datagrouped的临时视图,而非原DataFrame本身。后续对datagrouped做去重和透视时,原数据里的"Intl"值其实并没有真正被保存下来。
修复方案:改用.loc做安全赋值
替换成Pandas官方推荐的.loc索引方式,确保修改直接写入原数据:
# 先生成匹配国际价格本的掩码(注意要用datagrouped自身的列,避免索引不匹配) mask = datagrouped['Price Book Name'].str.contains("International", na=False) # 用.loc精准定位并修改 datagrouped.loc[mask, 'List Price Currency'] = 'Intl'
2. 检查去重步骤是否误删有效数据
你的去重代码:
df99 = datagrouped.drop_duplicates(['Product Code','List Price Currency'])
默认情况下drop_duplicates会保留每组重复组合的第一行。如果某个Product Code对应"Intl"的条目有多个,而恰好第一行的List Price是空值(NaN),那透视后就会出现NaN;或者某些有效"Intl"条目被意外当成重复项删除了。
验证与修复:
- 先排查
datagrouped中"Intl"行的价格是否为空:
# 筛选所有标记为Intl的行,查看空价格情况 intl_rows = datagrouped[datagrouped['List Price Currency'] == 'Intl'] print(intl_rows[intl_rows['List Price'].isna()])
- 如果存在空值,先填充或删除无效行;如果没有空值,修改去重逻辑确保保留有效行:
# 先按价格排序,把空值放到最后,再保留每组最后一个非空行 df99 = datagrouped.sort_values('List Price', na_position='last')\ .drop_duplicates(['Product Code','List Price Currency'], keep='last')
3. 透视前的最后校验
在执行透视前,先确认df99里每个产品都包含所有4种货币的条目:
# 统计每个产品对应的货币种类数 currency_count = df99.groupby('Product Code')['List Price Currency'].nunique() # 查看货币种类不足4种的产品 print(currency_count[currency_count < 4])
如果输出有结果,说明这些产品确实缺少对应货币的行,需要回到数据标记步骤,确认是否所有国际价格本的行都被正确标记为"Intl"。
按照这几个步骤排查,应该能解决透视后大量NaN的问题。
内容的提问来源于stack exchange,提问作者Warthog1
相关产品推荐
相关产品推荐

