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

为何Series.fillna()无法填充DataFrame中全部NaN值?

DataFrame填充NaN后仍存在空值的原因及解决办法

问题描述

我想用随机值填充DataFrame中的NaN值,操作步骤如下:

  1. 创建df1数据集
  2. 通过compound列切片筛选出compound为'a'的行得到df2
  3. 使用default_rng生成不重复的随机填充序列filler
  4. 调用df2.month.fillna(filler, inplace=True)执行填充,但结果中仍有NaN值,预期应全部填充完成,请问原因是什么?

原代码及输出

创建df1的代码:

import pandas as pd
import numpy as np

df1 = pd.DataFrame(
    list(zip(
        ['0001', '0001', '0002', '0003', '0004', '0004'],
        ['a', 'b', 'a', 'b', 'a', 'b'],
        ['USA', 'USA', 'USA', 'USA', 'USA', 'USA'],
        [np.nan, np.nan, 'Jan', np.nan, np.nan, 'Jan'],
        [1,2,3,4,5,6])),
    columns=['sample ID', 'compound', 'country', 'month', 'value'])
df1

df1输出:

sample ID   compound    country month   value
0   0001        a           USA     NaN     1
1   0001        b           USA     NaN     2
2   0002        a           USA     Jan     3
3   0003        b           USA     NaN     4
4   0004        a           USA     NaN     5
5   0004        b           USA     Jan     6

切片生成df2的代码:

df2 = df1.loc[df1.compound == 'a']
df2

df2输出:

sample ID  compound   country month   value
0   0001       a          USA     NaN     1
2   0002       a          USA     Jan     3
4   0004       a          USA     NaN     5

填充代码及输出:

from numpy.random import default_rng

rng = default_rng()
filler = rng.choice(len(df2.month), size=len(df2.month), replace=False)
filler = pd.Series(-abs(filler))

df2.month.fillna(filler, inplace=True)
df2

填充后输出:

sample ID    compound    country month   value
0   0001         a           USA     -1.0    1
2   0002         a           USA     Jan     3
4   0004         a           USA     NaN     5

原因分析

核心问题在于**fillna方法是按索引对齐进行填充的**:

  • 你生成的filler序列默认索引是[0,1,2],但df2的索引是[0,2,4]
  • 填充时,只有索引完全匹配的位置才会被处理:
    • df2索引0对应filler索引0,NaN被成功替换为-1.0
    • df2索引2对应filler索引2,但该位置原本不是NaN,所以无变化
    • df2索引4在filler中没有对应索引(filler最大索引为2),因此该位置的NaN无法被匹配填充,保留了下来

解决方案

让filler的索引与df2的索引完全一致,即可让fillna正确匹配所有NaN位置。有两种实现方式:

方式一:仅为NaN位置生成对应索引的填充序列(更高效)

from numpy.random import default_rng

rng = default_rng()
# 获取df2中month列的NaN位置索引
nan_indexes = df2[df2['month'].isna()].index
# 生成对应数量的不重复随机值
filler_values = rng.choice(range(1, 10), size=len(nan_indexes), replace=False)
# 创建与NaN位置索引一致的填充序列
filler = pd.Series(-abs(filler_values), index=nan_indexes)

df2['month'].fillna(filler, inplace=True)
df2

方式二:生成与df2全量索引一致的填充序列

from numpy.random import default_rng

rng = default_rng()
# 生成随机值并指定索引为df2的索引
filler = rng.choice(len(df2), size=len(df2), replace=False)
filler = pd.Series(-abs(filler), index=df2.index)

df2['month'].fillna(filler, inplace=True)
df2

两种方式执行后,df2的month列所有NaN都会被正确填充,不会再保留空值。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 15:32:23