trendline="ols"不显示线或报错因缺少statsmodels、数据含NaN、分组后子集不足2点;趋势线默认外推,需手动截断x范围;ols线性全局拟合快可解释,lowess局部平滑适非线性但不支持分组;公式和R²需手动计算添加。

为什么 trendline="ols" 有时不显示线,或报 statsmodels 错误
Plotly Express 的 trendline 参数依赖外部统计库,默认用 statsmodels 做 OLS 拟合。如果没装,会直接报错 ModuleNotFoundError: No module named 'statsmodels';即使装了,若数据含 NaN、非数值列或分组后子集过小(如某类别仅1个点),trendline 也会静默跳过该组,导致线“消失”。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 先运行
pip install statsmodels(plotly不自动带它) - 用
df.dropna(subset=[x_col, y_col])清洗关键列,别只靠px.scatter(..., trendline="ols")自动处理 - 若用
color分组,检查各组行数:df.groupby("category")[y_col].count(),确保每组 ≥2 行 - 临时验证拟合是否生效:加参数
trendline_scope="overall"强制全局拟合(绕过分组限制)
如何让趋势线只画在原始数据范围内,而不是延伸到坐标轴边界
Plotly 默认把趋势线外推到整个 x 轴范围,常造成误导——尤其当数据集中在左侧时,线会横跨空白区域。这不是 bug,而是 px.scatter 内部调用 statsmodels 后,用 go.Scatter 绘制时默认用了全轴 x 网格。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 不用
trendline参数,改用手动拟合 + 截断x值域 - 用
scipy.stats.linregress或numpy.polyfit算斜率和截距 - 生成预测
y时,x_pred = np.linspace(df[x_col].min(), df[x_col].max(), 50),再算对应y_pred - 用
fig.add_scatter(x=x_pred, y=y_pred, mode="lines", name="trend")追加线条,完全可控
trendline="lowess" 和 "ols" 的核心区别在哪,什么场景该选哪个
ols 是全局线性拟合,快、可解释(输出斜率/截距/R²),但假定关系是直线;lowess 是局部加权散点平滑,能捕捉非线性趋势,但计算慢、无解析表达式、对带宽(trendline_options={"frac": 0.3})敏感。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 先画
ols:快速看有无大致正/负相关,检查 R² 是否显著(px.scatter(..., trendline="ols", trendline_color_override="red")) - 若残差图明显弯曲,或业务上已知存在阈值效应(如用户活跃度随使用时长先升后缓),再试
lowess -
lowess必须设trendline_options:常用{"frac": 0.2}(20% 邻居点参与加权),值太小噪声大,太大变平滑成直线 - 注意:
lowess不支持分组(color),会报错ValueError: lowess does not support facet or color grouping
怎么在交互图里同时显示趋势线公式和 R² 值
Plotly Express 不提供内置方式把回归统计量写进图例或注释,trendline 只负责画线,不输出文本。想展示公式,得自己算、自己加 fig.add_annotation。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 用
statsmodels.api.OLS(y, sm.add_constant(x)).fit()获取results.params和results.rsquared - 构造字符串:
f"y = {slope:.2f}x + {intercept:.2f} (R² = {r2:.3f})" - 用
fig.add_annotation(xref="paper", yref="paper", x=0.02, y=0.98, xanchor="left", yanchor="top", text=formula, showarrow=False)左上角标注 - 若分组多,别硬塞所有公式——改用 hovertemplate:在
px.scatter中加hover_data=["trend_slope", "trend_r2"],提前把统计量算好存为列
trendline 是快捷入口,但真正控住拟合逻辑、范围和标注,还是得退到底层计算——尤其当数据有缺失、分组不均、或需要解释模型时,手动拟合那几行代码反而更稳。


















