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

使用np.random.normal替换缺失NaN值时所有值相同,如何优化代码?

问题原因

你当前代码输出所有替换值相同的核心原因是循环逻辑错误:每遍历到一个符合范围的随机值,就调用replace把整列所有的0统一替换为当前值,后续遍历的随机值会不断覆盖之前的替换结果,最终整列所有待替换值都等于循环最后一个符合要求的随机值。另外你要替换的是NaN,代码里写的替换目标是0,二者也存在不匹配的问题。

优化方案

高效向量化实现(推荐)

不需要循环或者列表推导,用pandas向量化操作性能更高,逻辑也更清晰:

  1. 首先将列中字符串格式的"NaN"转为pandas可识别的空值,统计需要填充的空值数量
import pandas as pd
import numpy as np

# 转成数值类型,无效值(比如字符串"NaN")会自动转为np.nan
data['Insulin'] = pd.to_numeric(data['Insulin'], errors='coerce')
# 统计需要填充的空值总数
na_cnt = data['Insulin'].isna().sum()
  1. 生成符合0-400范围的随机值,数量和待填充空值数一致
mu, sigma = 155, 118
# 多生成50%的随机值避免筛选后数量不足
random_arr = np.random.normal(mu, sigma, int(na_cnt * 1.5))
# 筛选出符合范围的值,取前na_cnt个
valid_random = random_arr[(random_arr > 0) & (random_arr < 400)][:na_cnt]
  1. 直接给空值位置赋值
data.loc[data['Insulin'].isna(), 'Insulin'] = valid_random

列表推导实现(按需求)

如果一定要用列表推导实现,可以写成如下形式:

mu, sigma = 155, 118
data['Insulin'] = [
    val if not pd.isna(val)
    # 每次取10个随机值直到拿到符合范围的,避免无限循环
    else next(x for x in np.random.normal(mu, sigma, 10) if 0 < x < 400)
    for val in data['Insulin']
]
注意事项
  • 提前确认数据集里的缺失值是真实的np.nan还是字符串格式的"NaN",后者需要先做类型转换才能被isna()识别
  • 生成随机值时建议多生成一部分,避免正态分布生成的值超出范围后不够填充使用
  • 非必要不建议用循环或者列表推导处理DataFrame列,向量化操作的执行效率会高很多

内容的提问来源于stack exchange,提问作者İzzet Türkalp Akbaşlı

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 22:45:02