使用 Golang 程式碼生成圖表的開源庫對比
本文的目標讀者
對用 Golang
程式碼生成折線圖、扇形圖等圖表有興趣的朋友。
本文摘要
主要介紹 Go 中用以繪圖的開源庫,分別是:
- GitHub – wcharczuk/go-chart: go chart is a basic charting library in go.
- GitHub – vicanso/go-charts: A charts library for Golang
- GitHub – vdobler/chart: Provide basic charts in go
- GitHub – gonum/plot: A repository for plotting and visualizing data
- GitHub – go-echarts/go-echarts: 🎨 The adorable charts library for Golang
我的需求是生成一個時間軸類型折線圖的圖片插入到我的報告中,前面兩個庫與我的需求比較符合,所以我會著重介紹;後面三個庫不滿足我的需求,在本文會大略帶過。如果懶得看正文,這是我總結的表格:
go-chart | go-charts | chart | plot | go-echarts | |
---|---|---|---|---|---|
使用文檔/示例完善 | ✅ | ✅ | ✅ | ✅ | ✅ |
學習成本 | 中 | 低 | 高 | 低 | 低 |
支援的圖表種類 | 少 | 少 | 少 | 中 | 多 |
支援時間軸 | ✅ | ✅ | ✅ | ❌ | ✅ |
支援輸出圖片 | ✅ | ✅ | ✅ | ✅ | ❌ |
支援設置標籤 | ✅ | ✅ | ✅ | ✅ | ✅ |
支援折線圖 | ✅ | ✅ | ❌ | ✅ | ✅ |
支援自定義圖表 | ❌ | ❌ | ❌ | ✅ | ❌ |
UI美觀 | ⭐️⭐️⭐️ | ⭐️⭐️⭐️⭐️ | ⭐️⭐️ | ⭐️⭐️ | ⭐️⭐️⭐️⭐️⭐️ |
還有一些庫,例如gg和 Go
內部自帶的 image/draw
包,在這裡就不介紹了,因為它們倆都屬於是繪製基礎圖形(圓形、正方形和矩形等)或者是對影像本身進行旋轉、縮放、添加文字等處理的,與本文所討論的繪製圖表不太一樣。
go-chart
go-chart
是一個簡單的 Golang
原生圖表庫,支援時間序列和連續折線圖。因此,go-chart
其實對數據量特別多的情況無法很好地適應,以及如果要在圖表中使用中文時,需要額外修改字體為支援中文的字體。
官方效果圖
-
曲線圖
-
單軸折線圖
-
雙軸折線圖
-
餅狀圖
-
柱狀圖
安裝
go get -u github.com/wcharczuk/go-chart
實際使用
我的需求是,從 influxdb
查詢數據,再將數據渲染為折線圖,程式碼如下:
/*
前面省略查詢 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 軸的程式碼會比較簡單,示例如下:
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
類型的圖表。
官方效果圖
主題為 light
與 grafana
。
安裝
go get -u github.com/vicanso/go-charts/v2
實際使用
同樣是從 influxdb
查詢數據,再處理數據生成圖表,程式碼如下:
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完全不在乎。
官方效果圖
安裝
go get -u github.com/vdobler/chart
詳細說明
這個庫支援的圖表類型有
- 帶狀圖
- 散點圖/函數圖
- 直方圖
- 條形圖和分類條形圖
- 扇形圖/環形圖
- 箱形圖
由上所述,這個介紹為「Provide basic charts「
的開源庫並不支援我需要的折線圖……
以及在介紹裡面,這個庫有以下幾個特點:
- 軸的值可以是線性、對數、分類或者時間/日期軸。
- 自動縮放具有很多選項。
- 抽動和標籤的精細控制。
輸出格式有txtg
、svgg
和imgg
這三種格式
plot
plot
的前身是code.google.com/p/plotinum
,它提供了用於 Go 中構建和繪製圖表的 API,主要用於將數據可視化。
官方效果圖
-
默認樣式
-
更細粒度的控制
-
自定義刻度線
-
帶誤差的點
-
條形圖
-
函數
-
直方圖
-
垂直箱形圖
-
水平箱形圖
-
四分點陣圖
-
氣泡圖
安裝
go get gonum.org/v1/plot/...
詳細說明
plot
庫其實包含以下四個部分:
plot
:提供了布局和繪圖的簡單介面;plotter
:使用plot提供的介面實現了一組標準的繪圖器,例如散點圖、條形圖、箱狀圖等。可以使用plotter提供的介面實現自己的繪圖器;plotutil
:為繪製常見圖形提供簡便的方法;vg
:封裝各種後端,並提供了一個通用矢量圖形 API。
引自《Go 每日一庫之 plot》
由上所述,我在使用 plot 庫時,發現裡面自帶的基本API不能滿足我的需求——我需要一個時間軸作為 x 軸,但是plot
庫默認的API中 x 軸只支援float64
類型的數據。
但是在plotter
中,你可以自定義一個繪圖器實現一些特殊的需求,以及你還可以使用社區製作的繪圖器,可以在這個網頁中查看其中一部分社區繪圖器:Community Plotters · gonum/plot Wiki · GitHub。
一些社區繪圖器的示例圖:
-
plotters/piechart at master · benoitmasson/plotters · GitHub
-
GitHub – pplcc/plotext: Extensions and custom plotters for the gonum plot packages
go-echarts
go-echarts
是一個專註數據可視化的圖表庫,參考了pyecharts
的一些設計思想;目前有 v1 和 v2 兩個版本,其中 v1 已經不再維護。
官方效果圖
安裝
go get -u github.com/go-echarts/go-echarts/v2
詳細介紹
go-echarts
是通過實現Apache ECharts的相關介面,來輕鬆生成全面又美觀的圖表。
因此,在編寫完生成圖表的程式碼後,你還需要將圖表渲染成一個HTML文件,或者是用一個HTTP
伺服器去渲染圖表,如圖:
以及這個開源庫渲染出來的圖表也是這幾個庫裡面最美觀的(畢竟是用HTML
程式碼渲染出來的)
總結
本文介紹了Go
中最主要的幾個繪製圖表的繪圖庫,其中對最為接近的兩個開源庫go-chart
和go-charts
進行了比較詳細的對比,其餘三個開源庫chart
、plot
和go-echarts
則是簡單介紹了一下。
這些開源庫各有各的特點,沒有絕對的優劣,希望能在大家需要挑選開源庫時給予一些參考。