含缺失数据的图表叠加线性回归时scipy.linregress返回nan问题求解
核心问题根因
- 为什么
linregress返回intercept=nan:Scipy的线性回归函数不会自动过滤数组中的缺失值(Excel空单元格读入pandas后默认转成的NaN),只要输入的x/y序列中存在哪怕一个空值,整个回归计算的输出结果都会是NaN,这是新手读取Excel做拟合最常见的踩坑点。 - 为什么插入拟合列时报长度不匹配:你用过滤掉空值的有效数据计算拟合值时,得到的结果数组长度等于有效非空数据的行数,但原DataFrame(比如提到的
cereal_df)的总行数是包含空单元格的全量长度,直接把短数组塞回全量DataFrame自然会触发长度不匹配错误。
分步可落地解决流程
第一步:先完成拟合前的数据清洗
从Excel读入的数据中,空单元格会被pandas自动识别为NaN,需要先把用于拟合的两列(时间、金属损耗值)中同时非空的行单独筛选出来,不能直接拿整列喂给回归函数。import pandas as pd import numpy as np import matplotlib.pyplot as plt from scipy.stats import linregress # 沿用你之前使用的cereal_df即可,读入时空单元格会自动转NaN cereal_df = pd.read_excel("你的金属损耗测量数据.xlsx") # 替换成你实际表格里的对应列名 valid_df = cereal_df.dropna(subset=["测量时间", "金属损耗量"]) x_valid = valid_df["测量时间"] y_valid = valid_df["金属损耗量"]第二步:用有效非空数据计算线性回归
此时输入给回归函数的序列没有缺失值,计算结果不会再出现全nan的情况:# 输入为纯非空序列,回归结果正常 res = linregress(x_valid, y_valid) print(f"线性回归结果: 斜率={res.slope:.2f}, 截距={res.intercept:.2f}, R²={res.rvalue**2:.2f}")第三步:解决拟合列插入的长度不匹配问题
不要直接把有效子集算出的短长度拟合值塞回原DataFrame,而是基于原DataFrame的全量时间列做矢量化计算,生成和原表长度完全一致的拟合值列:# ❌ 之前容易触发报错的写法 # y_fit = res.slope * x_valid + res.intercept # cereal_df["拟合值"] = y_fit # 问题根源:y_fit只有有效数据的行数,比全量cereal_df短,必然报长度不匹配 # ✅ 正确写法:基于原cereal_df的全量时间列计算拟合值 cereal_df["拟合损耗值"] = res.slope * cereal_df["测量时间"] + res.intercept第四步:在matplotlib图表上叠加趋势线
绘图时matplotlib会自动跳过原始数据列中的空值点,直接使用刚生成的全量拟合值列画趋势线即可:# 绘制原始测量值散点 plt.scatter(cereal_df["测量时间"], cereal_df["金属损耗量"], label="实际测量数据") # 叠加覆盖全时间范围的线性趋势线 plt.plot( cereal_df["测量时间"], cereal_df["拟合损耗值"], color="crimson", linewidth=2, label=f"线性趋势线 (R²={res.rvalue**2:.2f})" ) plt.xlabel("测量时间") plt.ylabel("金属损耗量") plt.legend() plt.grid(alpha=0.3) plt.show()
新手避坑提示
- 不管是用
scipy.stats.linregress还是np.polyfit,两个函数本身都不会自动处理缺失值,只要输入序列混入NaN,输出结果就会全为nan,必须先主动筛出有效非空数据再喂给回归函数。如果习惯用np.polyfit完成拟合,逻辑完全一致:先筛出有效非空的x、y值计算拟合系数,再基于原DataFrame的全量x列生成拟合值列,同样可以避免结果为nan、列长度不匹配的问题。 - 给DataFrame新增计算列时,优先基于原DataFrame的列做矢量化运算,不要把筛选子集上算出的短长度数组直接赋值回全量DataFrame,从根源上避免长度不匹配的报错。
- 如果Excel里的空单元格是用文本符号(比如
-、无数据)占位的,读入时要在pd.read_excel中加参数na_values=["-", "无数据"],把这些占位文本转成标准NaN,避免后续计算出现类型错误。
内容的提问来源于stack exchange,提问作者Adrian Beltran
相关产品推荐
相关产品推荐

