F#奇妙游(9):来一点点画图

F#绘图

如果Python没有Matplotlib,R没有ggplot,Matplab没有plot函数……就像阿珍爱上了阿强,能画图的脚本才是好脚本。当然,F#有画图包,但是F#在数据处理中的地位就像下面,这也是我们没办法的。
在这里插入图片描述

ScottPlot是一个基于.NET的绘图包,支持C#和F#,支持Windows、Linux和MacOS。选择ScottPlot是因为在nuget上搜索Plot,这个包排到第一,下载数也是排在第一。目前ScottPlot版本是4.1.64,V5正在开发中,还在beta阶段。那就用V4吧。

首先是脚本环境,最简单,在终端里运行dotnet fsi,就可以进入F#的REPL环境。也可以把下面的代码存成一个文件scatter.fsx,然后运行dotnet fsi scatter.fsx

#r "nuget: ScottPlot, 4.1.64"

open ScottPlot
let x = [|1.0..5.0|]
let y = [|for x in x -> x * x|]

let plt = Plot(400, 300)

plt.AddScatter(x, y)
plt.Title("scatter sample")
plt.SaveFig("scatter.png",scale=2.0)

运行结果就可以得到这个图片文件。
在这里插入图片描述

ScottPlot的其他功能

ScottPlot的V4的API帮助写得听清楚的。

大部分的时候,只需要创建一个Plot对象,调用Plot对象的方法来绘图,最后调用SaveFig方法保存图片就可以了。如果是在WinForm或者WPf中,还可以调用Render方法把图片渲染到窗口中。

这个Plot对象,可以反复使用,通过调用Clear方法,可以清空画布,然后重新绘制。这样子,就可以实现动态绘图。

//......
plt.Clear()
plt.AddScatter(x, y)
plt.Title("scatter sample")
plt.SaveFig("scatter.png",scale=2.0)

绘制多个图形

let x = [|1.0..5.0|]
let y = [|for x in x -> x * x|]

let y2 = [|for x in x -> x * x * x|]

let plt = Plot(400, 300)

let s1 = plt.AddScatter(x, y, label="squar")
let s2 = plt.AddScatter(x, y2)
s2.Label <- "cube"

plt.Title("scatter sample")
plt.Legend(true, Alignment.UpperLeft)

多次调用AddXXX就可以把多个图形画在同一个画布上,然后调用Legend方法,就可以显示图例。

图形对象

除了上面调用plt.AddScatter 方法,还可以直接创建图形对象,然后调用Plot对象的Add方法,把图形对象添加到画布上。

plt.Clear()

open System.Drawing

let xs = DataGen.Consecutive(51)
let sin = DataGen.Sin(51)

// instantiate a plottable
let splt = Plottable.ScatterPlot(xs, sin)

// customize its style or change its data as desired
splt.Color <- Color.Navy
splt.MarkerSize <- float32 10.0
splt.MarkerShape <- MarkerShape.filledDiamond
splt.Label <- "Navy"

// add it to the plot
plt.Add(splt)
plt.Legend(false)
plt.Title("Navy")

在这里插入图片描述

基本上,所有的图形对象都有Color、Label、MarkerSize、MarkerShape等属性,可以通过这些属性来定制图形的样式。

Jypyter Notebook

除了在脚本里面使用,在Jupyter Notebook中使用ScottPlot也是可以的。

#r "nuget: ScottPlot, 4.1.64"
open ScottPlot

// 把Plot对象转换为HTML,并注册到Jupyter的Formatter中
open Microsoft.DotNet.Interactive.Formatting
let plt2html (p:Plot) = p.GetImageHTML()
Formatter.Register<Plot>(plt2html, HtmlFormatter.MimeType)

后面这三行代码目前已经耗尽我的全部F#力,实现在Jupyter中插入ScottPlot的Plot对象。我在网上找了很久都没有找到,最后自己根据函数签名写出来的。

据说用Plotly.NET可以更加简单,这个包实现了Plotly.NET.Interactive,我目前还没有尝试,因为看着Plotly.NET的文档感觉没有ScottPlot来得清爽。

结果

就这样子,结果就比较美好。

在这里插入图片描述

总结

  1. .Net画图的包不缺
  2. 目前感觉画的图专业性略有差距
  3. F#调用、Jupyter都很丝滑

参考资料

ScottPlot@nuget

ScottPlot@github

ScottPlot Homepage

posted @ 2023-07-07 14:02  大福是小强  阅读(20)  评论(0编辑  收藏  举报  来源