使用 plot 繪製圖表

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

作為一個程式員,很多時候雖然我喜歡盯著 console 輸出的一堆數字看一些系統變化指標,但俗話說,一圖勝千言,如果能自動的將很多資料組建圖表展示,會更加清晰明了,而且能直接從變化的曲線上面得知更多的資訊。這也就是我特別喜歡 Prometheus + Grafana 的原因。

但很多項目,尤其是臨時的一些測試專案,我不可能為了看一個資料圖表就搭建一套 Prometheus + Grafana 系統,那樣效率太低,更多時候,我還是希望能有一個更簡單的工具將一些資料展示出來。

幸運的是,我們可以通過 plot 非常方便的做到。plot 是一個用 Go 語言實現的繪圖庫,我們可以通過它繪製非常豐富的圖表,並且可以輸出成多種格式。另外,plot 還提供了非常方便的 interface,我們可以通過它來定製自己的圖表。

簡單樣本

我們可以通過 plot 自己提供的 plotutil 工具繪製簡單的圖形。

Line and Points

因為最近剛在看可汗學院的微觀經濟學,所以就以 price 和 quantity demand 來作為第一個例子,價格和需求數量通常是成反比的關係,繪製的圖形應該是一條下降的曲線。為了簡化程式碼數,這裡特意去掉了錯誤處理。

import (    "github.com/gonum/plot"    "github.com/gonum/plot/plotter"    "github.com/gonum/plot/plotutil"    "github.com/gonum/plot/vg")func main() {    p, _ := plot.New()    p.Title.Text = "Hello Price"    p.X.Label.Text = "Quantity Demand"    p.Y.Label.Text = "Price"    points := plotter.XYs{        {2.0, 60000.0},        {4.0, 40000.0},        {6.0, 30000.0},        {8.0, 25000.0},        {10.0, 23000.0},    }    plotutil.AddLinePoints(p, points)    p.Save(4*vg.Inch, 4*vg.Inch, "price.png")}

執行之後,我們就能可以得到一個命名為 price 的 png 檔案,看起來就是這樣的:


Histograms

在用 Prometheus 和 Grafana 的時候,我其實對一些 histogram 的 metric 的展示不怎麼滿意,因為 Grafana 的 X 軸是時間相關的,所以並不能展示柱狀圖,只能使用 histogram_quantile 或者其他函數得到相關的變化曲線,用 plot 則可以非常方便的將 Prometheus 的資料拿出來畫圖。

一個簡單的例子:

import (    "github.com/gonum/plot"    "github.com/gonum/plot/plotter"    "github.com/gonum/plot/vg")func main() {    p, _ := plot.New()    p.Title.Text = "Histogram"    bins := plotter.XYs{        {10, 10},        {20, 20},        {30, 50},        {40, 20},        {50, 10},    }    h, _ := plotter.NewHistogram(bins, 5)    p.Add(h)    p.Save(4*vg.Inch, 4*vg.Inch, "histogram.png")}

柱狀圖如下:


自定製 Plotter

Plotter

除了使用 plot 提供的圖表之外,我們還可以非常方便定製自己的圖表。這裡我們簡單的畫一個邊長為 20 的正方形。首先定義 Sqaures:

type Squares struct {    plotter.XYs}

Squares 裡面就只有一批 points,用來表示各個正方形的中心 point。然後我們實現 Plotter 的 Plot 函數,如下:

func (s *Squares) Plot(c draw.Canvas, plt *plot.Plot) {    trX, trY := plt.Transforms(&c)    c.SetColor(color.RGBA{R: 196, B: 128, A: 255})    r := vg.Length(10.0)    for _, p := range s.XYs {        p1 := vg.Point{trX(p.X) - r, trY(p.Y) - r}        p2 := vg.Point{trX(p.X) - r, trY(p.Y) + r}        p3 := vg.Point{trX(p.X) + r, trY(p.Y) + r}        p4 := vg.Point{trX(p.X) + r, trY(p.Y) - r}        var p vg.Path        p.Move(p1)        p.Line(p2)        p.Line(p3)        p.Line(p4)        p.Line(p1)        p.Close()        c.Fill(p)    }}

上面的 Plot 函數裡面,我們使用 plt.Transforms(&c) ,得到兩個轉換函式,能夠將後面正方形的 point 轉換到實際的 canvas 的 point 上面。

func main() {    points := plotter.XYs{        {2, 2},        {4, 4},        {6, 6},        {8, 8},        {10, 10},    }    s := Squares{points}    p, _ := plot.New()    p.Title.Text = "Squares"    p.X.Label.Text = "X"    p.Y.Label.Text = "Y"    p.X.Min = 0    p.X.Max = 20    p.Y.Min = 0    p.Y.Max = 20    p.Add(&s)    p.Save(4*vg.Inch, 4*vg.Inch, "squares.png")}

建立一個 Sqaures,然後執行,得到圖表:


DataRanger

在上面的例子中,我們使用了類似 p.X.Min = 0, p.X.Max = 20 的方式來設定整個圖表的範圍,但實際我們更希望能動態調整,因為我們不可能預估到實際的範圍到底有多大,這裡可以使用 DataRange 來實現:

func (s *Squares) DataRange() (float64, float64, float64, float64) {    return plotter.XYRange(s.XYs)}

得到圖表如下:


GlyphBoxer

雖然通過 DataRange 能解決範圍的問題,但我們又發現,一些正方形在邊界上面被切掉了,這主要是因為我們是以正方形的中心繪製的,一個解決方案就是 DataRange 返回更大的區間,能夠覆蓋掉整個正方向。但另一個更好的辦法就是使用 GlyphBoxes,用來顯示的告訴要繪製的圖表的位置和大小。

func (s *Squares) GlyphBoxes(plt *plot.Plot) []plot.GlyphBox {    boxes := make([]plot.GlyphBox, len(s.XYs))    r := vg.Length(10.0)    for i, p := range s.XYs {        boxes[i].X = plt.X.Norm(p.X)        boxes[i].Y = plt.Y.Norm(p.Y)        boxes[i].Rectangle = vg.Rectangle{            Min: vg.Point{X: -r, Y: -r},            Max: vg.Point{X: +r, Y: +r},        }    }    return boxes}

現在看起來就是這樣了:


後記

可以看到,使用 plot,我們可以非常方便的繪製圖表。當然,plot 的功能遠遠不止上面說的那麼簡單,譬如我們可以直接擷取 Prometheus 的資料然後繪圖,在發送給 Slack,或者畫一個 PieChart。

後面,我們也會考慮在一些內部的系統上面使用 plot,譬如效能測試架構,每次提交之後,跑很多效能測試,收集到每次的效能測試結果,使用 plot 繪圖展示等等。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.