You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用fillna()填充DataFrame空值失效及合并重复问题排查

问题:替换DataFrame中指定国家的NaN值

数据背景

主DataFrame(df)包含多国数据,其中委内瑞拉的Inflation字段全为NaN,尾部数据如下:

{'country': {640: 'Venezuela, RB', 641: 'Venezuela, RB', 642: 'Venezuela, RB', 643: 'Venezuela, RB', 644: 'Venezuela, RB', 645: 'Venezuela, RB', 646: 'Venezuela, RB', 647: 'Venezuela, RB', 648: 'Venezuela, RB', 649: 'Venezuela, RB'}, 'year': {640: '1995', 641: '1996', 642: '1997', 643: '1998', 644: '1999', 645: '2000', 646: '2001', 647: '2002', 648: '2003', 649: '2004'}, 'Inflation': {640: nan, 641: nan, 642: nan, 643: nan, 644: nan, 645: nan, 646: nan, 647: nan, 648: nan, 649: nan}}

需要用另一个DataFrame(df_V)的Inflation值替换上述NaN,df_V数据如下:

{'country': {525: 'Venezuela, RB', 526: 'Venezuela, RB', 527: 'Venezuela, RB', 528: 'Venezuela, RB', 529: 'Venezuela, RB', 530: 'Venezuela, RB', 531: 'Venezuela, RB', 532: 'Venezuela, RB', 533: 'Venezuela, RB', 534: 'Venezuela, RB'}, 'year': {525: 1980, 526: 1981, 527: 1982, 528: 1983, 529: 1984, 530: 1985, 531: 1986, 532: 1987, 533: 1988, 534: 1989}, 'Inflation': {525: 20.94726767651016, 526: 20.588477814454166, 527: 10.163124878901897, 528: 6.642275237205508, 529: 6.920491255381944, 530: 17.043721529702637, 531: 9.95424654983843, 532: 12.824921633483587, 533: 38.2611159060269, 534: 36.431816868877775}}

尝试的方法及问题

  1. 使用combine_first合并
    执行代码:

    df_merged = df.set_index(['country','year']).combine_first(df_V.set_index(['country','year'])).reset_index()
    df_merged.tail(50)
    

    问题:结果中出现两组委内瑞拉数据,新数据被追加到末尾,未替换原NaN。

  2. 使用fillna()填充
    执行代码:

    df['Inflation'] = df['Inflation'].fillna(df_V['Inflation'])
    df.tail(25)
    

    问题:原df中的NaN未被替换,相同方法对其他国家有效,且已确认NaN为字符串类型。

原因分析及解决方案

核心原因

  1. combine_first失效原因:主df的year字段是字符串类型(如'1995'),而df_V的year是整数类型(如1980),设置复合索引时类型不匹配,导致无法匹配行,因此两组数据被分别保留。
  2. fillna失效原因:fillna默认按索引位置匹配填充,主df中委内瑞拉行的索引是640-649,而df_V的索引是525-534,位置不对应;若NaN是字符串'NaN'而非numpy的nan,fillna也无法识别。

解决方案

步骤1:统一字段类型(若存在类型不匹配)

先将两个DataFrame的year转成同一类型,同时将字符串'NaN'转为numpy的nan(如果需要):

import numpy as np

# 统一year类型为整数
df['year'] = df['year'].astype(int)
df_V['year'] = df_V['year'].astype(int)

# 若Inflation中的NaN是字符串类型,转为numpy nan
df['Inflation'] = df['Inflation'].replace('NaN', np.nan)

步骤2:按需求选择填充方式

场景A:仅按位置替换(不管年份,将df_V的10个值依次填入df的委内瑞拉NaN行)

直接筛选出委内瑞拉的行,替换其Inflation值:

# 筛选委内瑞拉的行
venezuela_mask = df['country'] == 'Venezuela, RB'
# 将df_V的Inflation值按顺序填充
df.loc[venezuela_mask, 'Inflation'] = df_V['Inflation'].values
场景B:按年份匹配替换(若后续修正年份数据后需要)

当两个DataFrame的country和year完全匹配时,用复合索引合并填充:

# 设置复合索引后合并
df_combined = df.set_index(['country', 'year'])
df_V_combined = df_V.set_index(['country', 'year'])
# 用df_V的Inflation填充df的NaN
df_combined['Inflation'] = df_combined['Inflation'].combine_first(df_V_combined['Inflation'])
# 重置索引
df_merged = df_combined.reset_index()

内容的提问来源于stack exchange,提问作者Python_Learner_1997

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 07:07:05