如何用Plotly.NET绘制带线性回归线的分组散点图?
在Plotly.NET中实现分组散点图+线性回归线的问题
我希望在Plotly.NET中对Deedly数据框的两列绘制散点图,同时按第三列进行分组,并在同一张图中添加类似Python中seaborn.lmplot的线性回归线。
在Python中对应的实现代码是:
sns.lmplot(data=penguins, x="bill_length_mm", y="bill_depth_mm", hue="species")
目前我仅用Plotly.NET实现了简单散点图:
( df.["rating"].Values, df.["calories"].Values ) ||> Seq.zip |> Chart.Point
现咨询两个问题:
- 如何添加类似seaborn的线性回归线,是否需手动实现?
- 按第三列分组的优雅方案是什么?
解决方案
1. 按第三列分组的优雅实现
可以先按分组列对DataFrame进行分组,为每个分组生成独立散点图后,将所有子图合并到同一张画布中。假设分组列为"category",代码示例如下:
open Deedle open Plotly.NET // 按分组列拆分数据框 let groups = df |> Frame.groupRowsByString "category" // 为每个分组生成散点图 let scatterCharts = groups |> Series.map (fun groupName groupDf -> Chart.Point( x = groupDf.["rating"].Values, y = groupDf.["calories"].Values, Name = groupName ) ) |> Series.values // 合并所有散点图 let groupedScatter = Chart.Combine scatterCharts
2. 添加线性回归线(无需完全手动实现)
Plotly.NET没有一键生成回归线的内置API,但可以借助MathNet.Numerics库计算线性回归参数,生成拟合线后与散点图合并,步骤如下:
- 通过NuGet安装
MathNet.Numerics.FSharp - 为每个分组计算拟合线数据
- 生成回归线折线图并与对应散点图合并
代码示例:
open MathNet.Numerics.LinearRegression // 定义计算线性回归拟合点的函数 let getRegressionLine (x: seq<float>) (y: seq<float>) = let xArr = x |> Seq.toArray let yArr = y |> Seq.toArray // 计算线性回归系数:截距b,斜率a(y = a*x + b) let (b, a) = SimpleRegression.Fit(xArr, yArr) // 获取x的范围,生成拟合线的x点 let xMin = xArr |> Array.min let xMax = xArr |> Array.max let regressionX = [xMin; xMax] let regressionY = regressionX |> List.map (fun xVal -> a * xVal + b) (regressionX, regressionY) // 为每个分组生成带回归线的组合图 let chartsWithRegression = groups |> Series.map (fun groupName groupDf -> let x = groupDf.["rating"].Values let y = groupDf.["calories"].Values // 散点图 let scatter = Chart.Point(x, y, Name = groupName) |> Chart.withMarkerStyle(Opacity = 0.7) // 回归线图 let (regX, regY) = getRegressionLine x y let regressionLine = Chart.Line(regX, regY, Name = sprintf "%s 回归线" groupName) |> Chart.withLineStyle(Dash = StyleParam.DrawingStyle.Dash) // 合并当前分组的散点和回归线 Chart.Combine [scatter; regressionLine] ) |> Series.values // 合并所有分组的图到一张画布 let finalChart = Chart.Combine chartsWithRegression
如果需要更平滑的回归线,可修改getRegressionLine中的regressionX,生成更多介于xMin和xMax之间的点:
let regressionX = [for x in xMin .. 0.1 .. xMax -> x]
内容的提问来源于stack exchange,提问作者alkasai
相关产品推荐
相关产品推荐

