• 【Golang】使用代码绘制图表的开源库对比


    本文的目标读者#

    对用 Golang 代码生成折线图、扇形图等图表有兴趣的朋友。

    本文摘要#

    主要介绍 Go 中用以绘图的开源库,分别是:

    我的需求是生成一个时间轴类型折线图的图片插入到我的报告中,前面两个库与我的需求比较符合,所以我会着重介绍;后面三个库不满足我的需求,在本文会大略带过。如果懒得看正文,这是我总结的表格:

    go-chart go-charts chart plot go-echarts
    使用文档/示例完善
    学习成本
    支持的图表种类
    支持时间轴
    支持输出图片
    支持设置标签
    支持折线图
    支持自定义图表
    UI美观 ⭐️⭐️⭐️ ⭐️⭐️⭐️⭐️ ⭐️⭐️ ⭐️⭐️ ⭐️⭐️⭐️⭐️⭐️

    还有一些库,例如ggGo 内部自带的 image/draw 包,在这里就不介绍了,因为它们俩都属于是绘制基础图形(圆形、正方形和矩形等)或者是对图像本身进行旋转、缩放、添加文字等处理的,与本文所讨论的绘制图表不太一样。

    go-chart#

    go-chart是一个简单的 Golang 原生图表库,支持时间序列和连续折线图。因此,go-chart 其实对数据量特别多的情况无法很好地适应,以及如果要在图表中使用中文时,需要额外修改字体为支持中文的字体。

    官方效果图#

    1. 曲线图

    2. 单轴折线图

    3. 双轴折线图

    4. 饼状图

    5. 柱状图

    安装#

    Copy
    go get -u github.com/wcharczuk/go-chart

    实际使用#

    我的需求是,从 influxdb 查询数据,再将数据渲染为折线图,代码如下:

    Copy
    /* 前面省略查询 influxdb 过程 */ xValue := []string{} yValue := []float64{} // 处理查询到的结果数据 for _, value := range allRequest[0].Series[0].Values { if value[1] == nil { yValue = append(yValue, 0) t := value[0].(string) xValue = append(xValue, t) } else { fmt.Println("value:", value[1]) x, _ := value[1].(json.Number) s, _ := x.Float64() yValue = append(yValue, s) fmt.Println(reflect.TypeOf(value[0])) t := value[0].(string) xValue = append(xValue, t) } } // 时间轴的显示格式 format := chart.TimeValueFormatterWithFormat("15:04") lenX := len(xValue) // X轴内容 xValues 及 X轴坐标 ticks var xValues []time.Time var ticks []chart.Tick for i := 0; i < lenX; i++ { t, _ := time.Parse( time.RFC3339, xValue[i]) x := t.Local() xValues = append(xValues, x) ticks = append(ticks, chart.Tick{Value: getNsec(t), Label: format(t)}) } // 定义曲线 var series []chart.Series series = append(series, chart.TimeSeries{ XValues: xValues, YValues: yValue, Style: chart.Style{ StrokeColor: chart.GetDefaultColor(0).WithAlpha(64), FillColor: drawing.ColorFromHex("9ADFEA"), }, }) // 设置图表的样式 lineChartStyle := chart.Style{ Padding: chart.Box{ Top: 30, Left: 30, Right: 30, Bottom: 30, }, } graph := chart.Chart{ Title: "All Requests", Background: lineChartStyle, Width: 1280, Height: 500, XAxis: chart.XAxis{ Name: "", ValueFormatter: format, Ticks: ticks, }, YAxis: chart.YAxis{ Name: "", }, Series: series, } graph.Elements = []chart.Renderable{ chart.LegendLeft(&graph), } // 生成图片 var imgContent bytes.Buffer err = graph.Render(chart.PNG, &imgContent) if err != nil { fmt.Println(err) } f, _ := os.Create("test.png") _, _ = f.Write(imgContent.Bytes())

    这里查询了10分钟的数据,生成的图片为

    可以看到图表上的 x 轴已经看不清了,这是因为数据点非常多,而 go-chart 没有对此进行适配。

    在数据点较少的情况下,比如只查询1分钟的数据,生成的图片为:

    优点#

    • 图表的自定义程度高,例如可以选择给曲线填充颜色等

    缺点#

    • 使用比较复杂
      我想画的图表的 x 轴是时间轴类型,在这个库中绘制时间轴类型的 x 轴需要额外把数据进行处理为 Time.time类型。如使用 float64 类型的 x 轴的代码会比较简单,示例如下:
    Copy
    graph := chart.Chart{ Series: []chart.Series{ chart.ContinuousSeries{ XValues: []float64{1.0, 2.0, 3.0, 4.0}, YValues: []float64{1.0, 2.0, 3.0, 4.0}, }, }, } buffer := bytes.NewBuffer([]byte{}) err := graph.Render(chart.PNG, buffer)
    • 图表的样式不够精美
      下面有go-charts的 demo 图,可以对比一下,确实是不如它好看。

    go-charts#

    Go-charts 是国内的程序员在 go-chart 的基础上优化了图表的生成方式,同时还优化了图表的样式。目前支持 line, bar, horizontal bar, pie ,radar, funnel 以及table类型的图表。

    官方效果图#

    主题为 lightgrafana

    安装#

    Copy
    go get -u github.com/vicanso/go-charts/v2

    实际使用#

    同样是从 influxdb 查询数据,再处理数据生成图表,代码如下:

    Copy
    xValue := []string{} yValue := [][]float64{} // 处理结果 for _, value := range allRequest[0].Series[0].Values { tempY := []float64{} resultX := value[0].(string) xValue = append(xValue, resultX) number, _ := value[1].(json.Number) resultY, _ := number.Float64() tempY = append(tempY, resultY) } // 对 x 轴格式化 原:2022-07-29T09:24:10Z,新:09:24:10 formatXValue := []string{} for _, x := range xValue { formatTime, err := time.Parse(time.RFC3339, x) if err != nil { } formatX := formatTime.Local().Format("15:04:05") formatXValue = append(formatXValue, formatX) } f := false // 设置 x 轴的样式 // 字体文件需要自行下载 buff, err := ioutil.ReadFile("./TencentSans-W7.ttf") if err != nil { panic(err) } err = charts.InstallFont("noto", buff) if err != nil { panic(err) } // 渲染图表 p, err := charts.LineRender( yValue, charts.FontFamilyOptionFunc("noto"), charts.TitleTextOptionFunc("全部请求"), charts.XAxisDataOptionFunc(xValue), func(opt *charts.ChartOption) { opt.XAxis.BoundaryGap = &f opt.Padding = charts.Box{Left: 20, Right: 50, Top: 20, Bottom: 20} }, charts.ThemeOptionFunc("grafana"), charts.WidthOptionFunc(1000), )

    查询10分钟的数据,生成的效果图为:

    如果将主题换为 light,效果图如下

    如果只查询1分钟的数据,效果图如下

    从上面的效果图中可以发现,go-charts在数据量比较大的情况下,优化了 x 轴的展示,让数据不会挤在一起;以及样式也更好看一点。

    优点#

    • 样式好看
      看上面的图,一目了然
    • 使用简单
      从代码中也可以看出来,go-charts对 x 轴和 y 轴的类型做了额外一层封装,x 轴的类型为 string,y 轴的类型为 [][]float64,只需要传相应类型的数据就可以直接渲染图表。
      并且由于 y 轴的 []float64 就表示一条曲线,所以如果要在图表中增加渲染的曲线也比在 go-chart中要更简单——直接给 y 轴数据 append 一个新的 []float64 数据即可。

    缺点#

    • 自定义的自由度没有 go-chart
      例如go-charts中暂不支持用颜色填充曲线,以及不能自定义曲线的颜色等。

    • 当曲线超过9条后,曲线的颜色会开始重复

    作者的回复是他自己的使用场景只需要用到5条曲线左右,建议如果涉及到太多的曲线,最好分开画图。

    不过都不是什么大问题,是一个很好用的开源库。

    chart#

    前面这三个库的名字真是太像了,并且这三个库都提供基础图表的绘制功能。但是这个库更关注自动缩放、误差线和对数图等图表,并且对漂亮UI完全不在乎。

    官方效果图#

    安装#

    Copy
    go get -u github.com/vdobler/chart

    详细说明#

    这个库支持的图表类型有

    • 带状图
    • 散点图/函数图
    • 直方图
    • 条形图和分类条形图
    • 扇形图/环形图
    • 箱形图

    由上所述,这个介绍为“Provide basic charts“的开源库并不支持我需要的折线图……

    以及在介绍里面,这个库有以下几个特点:

    • 轴的值可以是线性、对数、分类或者时间/日期轴。
    • 自动缩放具有很多选项。
    • 抽动和标签的精细控制。

    输出格式有txtgsvggimgg这三种格式

    plot#

    plot的前身是code.google.com/p/plotinum,它提供了用于 Go 中构建和绘制图表的 API,主要用于将数据可视化。

    官方效果图#

    • 默认样式

    • 更细粒度的控制

    • 自定义刻度线

    • 带误差的点

    • 条形图

    • 函数

    • 直方图

    • 垂直箱形图

    • 水平箱形图

    • 四分位图

    • 气泡图

    安装#

    Copy
    go get gonum.org/v1/plot/...

    详细说明#

    plot库其实包含以下四个部分:

    1. plot:提供了布局和绘图的简单接口;
    2. plotter:使用plot提供的接口实现了一组标准的绘图器,例如散点图、条形图、箱状图等。可以使用plotter提供的接口实现自己的绘图器;
    3. plotutil:为绘制常见图形提供简便的方法;
    4. vg:封装各种后端,并提供了一个通用矢量图形 API。
      引自《Go 每日一库之 plot》

    由上所述,我在使用 plot 库时,发现里面自带的基本API不能满足我的需求——我需要一个时间轴作为 x 轴,但是plot库默认的API中 x 轴只支持float64类型的数据。

    但是在plotter中,你可以自定义一个绘图器实现一些特殊的需求,以及你还可以使用社区制作的绘图器,可以在这个网页中查看其中一部分社区绘图器:Community Plotters · gonum/plot Wiki · GitHub

    一些社区绘图器的示例图:

    1. plotters/piechart at master · benoitmasson/plotters · GitHub

    2. GitHub - pplcc/plotext: Extensions and custom plotters for the gonum plot packages

    go-echarts#

    go-echarts是一个专注数据可视化的图表库,参考了pyecharts的一些设计思想;目前有 v1 和 v2 两个版本,其中 v1 已经不再维护。

    官方效果图#


    安装#

    Copy
    go get -u github.com/go-echarts/go-echarts/v2

    详细介绍#

    go-echarts是通过实现Apache ECharts的相关接口,来轻松生成全面又美观的图表。

    因此,在编写完生成图表的代码后,你还需要将图表渲染成一个HTML文件,或者是用一个HTTP服务器去渲染图表,如图:

    以及这个开源库渲染出来的图表也是这几个库里面最美观的(毕竟是用HTML代码渲染出来的)

    总结#

    本文介绍了Go中最主要的几个绘制图表的绘图库,其中对最为接近的两个开源库go-chartgo-charts进行了比较详细的对比,其余三个开源库chartplotgo-echarts则是简单介绍了一下。
    这些开源库各有各的特点,没有绝对的优劣,希望能在大家需要挑选开源库时给予一些参考。

  • 相关阅读:
    每日刷题记录 (一)
    Newtonsoft.Json/Json.NET忽略序列化时的意外错误
    tftp服务的搭建
    C# Timer定时器
    93. 复原 IP 地址
    springboot毕设项目超市收银系统ybza4(java+VUE+Mybatis+Maven+Mysql)
    第十四届蓝桥杯(第二期)模拟赛试题与题解 C++
    ChatGPT成精了!
    Node基础
    C/C++程序设计和预处理
  • 原文地址:https://www.cnblogs.com/chrystal/p/16584722.html