// Copyright ©2015 The Gonum Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package plotter_test import ( "image/color" "log" "golang.org/x/exp/rand" "gonum.org/v1/plot" "gonum.org/v1/plot/plotter" "gonum.org/v1/plot/vg" ) func ExampleBarChart() { // Create the plot values and labels. values := plotter.Values{0.5, 10, 20, 30} verticalLabels := []string{"A", "B", "C", "D"} horizontalLabels := []string{"Label A", "Label B", "Label C", "Label D"} // Create a vertical BarChart p1 := plot.New() verticalBarChart, err := plotter.NewBarChart(values, 0.5*vg.Centimeter) if err != nil { log.Panic(err) } p1.Add(verticalBarChart) p1.NominalX(verticalLabels...) err = p1.Save(100, 100, "testdata/verticalBarChart.png") if err != nil { log.Panic(err) } // Create a horizontal BarChart p2 := plot.New() horizontalBarChart, err := plotter.NewBarChart(values, 0.5*vg.Centimeter) horizontalBarChart.Horizontal = true // Specify a horizontal BarChart. if err != nil { log.Panic(err) } p2.Add(horizontalBarChart) p2.NominalY(horizontalLabels...) err = p2.Save(100, 100, "testdata/horizontalBarChart.png") if err != nil { log.Panic(err) } // Now, make a different type of BarChart. groupA := plotter.Values{20, 35, 30, 35, 27} groupB := plotter.Values{25, 32, 34, 20, 25} groupC := plotter.Values{12, 28, 15, 21, 8} groupD := plotter.Values{30, 42, 6, 9, 12} p := plot.New() p.Title.Text = "Bar chart" p.Y.Label.Text = "Heights" w := vg.Points(8) barsA, err := plotter.NewBarChart(groupA, w) if err != nil { log.Panic(err) } barsA.Color = color.RGBA{R: 255, A: 255} barsA.Offset = -w / 2 barsB, err := plotter.NewBarChart(groupB, w) if err != nil { log.Panic(err) } barsB.Color = color.RGBA{R: 196, G: 196, A: 255} barsB.Offset = w / 2 barsC, err := plotter.NewBarChart(groupC, w) if err != nil { log.Panic(err) } barsC.XMin = 6 barsC.Color = color.RGBA{B: 255, A: 255} barsC.Offset = -w / 2 barsD, err := plotter.NewBarChart(groupD, w) if err != nil { log.Panic(err) } barsD.Color = color.RGBA{B: 255, R: 255, A: 255} barsD.XMin = 6 barsD.Offset = w / 2 p.Add(barsA, barsB, barsC, barsD) p.Legend.Add("A", barsA) p.Legend.Add("B", barsB) p.Legend.Add("C", barsC) p.Legend.Add("D", barsD) p.Legend.Top = true p.NominalX("Zero", "One", "Two", "Three", "Four", "", "Six", "Seven", "Eight", "Nine", "Ten") p.Add(plotter.NewGlyphBoxes()) err = p.Save(300, 250, "testdata/barChart2.png") if err != nil { log.Panic(err) } // Now, make a stacked BarChart. p = plot.New() p.Title.Text = "Bar chart" p.Y.Label.Text = "Heights" w = vg.Points(15) barsA, err = plotter.NewBarChart(groupA, w) if err != nil { log.Panic(err) } barsA.Color = color.RGBA{R: 255, A: 255} barsA.Offset = -w / 2 barsB, err = plotter.NewBarChart(groupB, w) if err != nil { log.Panic(err) } barsB.Color = color.RGBA{R: 196, G: 196, A: 255} barsB.StackOn(barsA) barsC, err = plotter.NewBarChart(groupC, w) if err != nil { log.Panic(err) } barsC.Offset = w / 2 barsC.Color = color.RGBA{B: 255, A: 255} barsD, err = plotter.NewBarChart(groupD, w) if err != nil { log.Panic(err) } barsD.StackOn(barsC) barsD.Color = color.RGBA{B: 255, R: 255, A: 255} p.Add(barsA, barsB, barsC, barsD) p.Legend.Add("A", barsA) p.Legend.Add("B", barsB) p.Legend.Add("C", barsC) p.Legend.Add("D", barsD) p.Legend.Top = true p.NominalX("Zero", "One", "Two", "Three", "Four") p.Add(plotter.NewGlyphBoxes()) err = p.Save(250, 250, "testdata/stackedBarChart.png") if err != nil { log.Panic(err) } } // This example shows a bar chart with both positive and negative values. func ExampleBarChart_positiveNegative() { rnd := rand.New(rand.NewSource(1)) // Create random data points between -1 and 1. const n = 6 data1 := make(plotter.Values, n) data2 := make(plotter.Values, n) net := make(plotter.XYs, n) // net = data1 + data2 for i := 0; i < n; i++ { data1[i] = rnd.Float64()*2 - 1 data2[i] = rnd.Float64()*2 - 1 net[i].X = data1[i] + data2[i] net[i].Y = float64(i) } // splitBySign splits an array into two arrays containing the positive and // negative values, respectively, from the original array. splitBySign := func(d plotter.Values) (pos, neg plotter.Values) { pos = make(plotter.Values, len(d)) neg = make(plotter.Values, len(d)) for i, v := range d { if v > 0 { pos[i] = v } else { neg[i] = v } } return } data1Pos, data1Neg := splitBySign(data1) data2Pos, data2Neg := splitBySign(data2) const barWidth = 0.3 * vg.Centimeter pos1, err := plotter.NewBarChart(data1Pos, barWidth) if err != nil { log.Panic(err) } pos2, err := plotter.NewBarChart(data2Pos, barWidth) if err != nil { log.Panic(err) } neg1, err := plotter.NewBarChart(data1Neg, barWidth) if err != nil { log.Panic(err) } neg2, err := plotter.NewBarChart(data2Neg, barWidth) if err != nil { log.Panic(err) } netDots, err := plotter.NewScatter(net) if err != nil { log.Panic(err) } netDots.Radius = vg.Points(1.25) pos2.StackOn(pos1) // Specify that pos2 goes on top of pos1. neg2.StackOn(neg1) // Specify that neg2 goes on top of neg1. color1 := color.NRGBA{R: 112, G: 22, B: 0, A: 255} color2 := color.NRGBA{R: 91, G: 194, B: 54, A: 100} pos1.Color, neg1.Color = color1, color1 pos2.Color, neg2.Color = color2, color2 // Specify that we want a horizontal bar chart. pos1.Horizontal, pos2.Horizontal, neg1.Horizontal, neg2.Horizontal = true, true, true, true // Create a line at zero. zero, err := plotter.NewLine(plotter.XYs{{0, 0}, {0, 5}}) if err != nil { log.Panic(err) } p := plot.New() p.Add(zero, pos1, pos2, neg1, neg2, netDots) p.NominalY("Alpha", "Bravo", "Charlie", "Echo", "Foxtrot", "Golf") p.Legend.Add("1", pos1) p.Legend.Add("2", pos2) p.Legend.Add("Sum", netDots) p.Legend.Top = true p.Legend.ThumbnailWidth = 2 * vg.Millimeter p.Legend.TextStyle.Font.Size = 2 * vg.Millimeter err = p.Save(100, 100, "testdata/barChart_positiveNegative.png") if err != nil { log.Panic(err) } }