Two-dimensional grouped bar charts

## Example

The following example dataset:

``````val sales = Map(
("apple", 2011) -> 43.0,
("apple", 2012) -> 83.8,
("banana", 2011) -> 11.3,
("banana", 2012) -> 77.9,
("coconut", 2011) -> 88.0,
("coconut", 2012) -> 10.1
)
// sales: scala.collection.immutable.Map[(String, Int),Double] = Map((coconut,2011) -> 88.0, (banana,2012) -> 77.9, (apple,2012) -> 83.8, (apple,2011) -> 43.0, (banana,2011) -> 11.3, (coconut,2012) -> 10.1)
``````

Shared imports

``````import cats.implicits._
import spire.implicits.DoubleAlgebra
import spire.implicits.IntAlgebra
import axle.visualize.BarChartGrouped
import axle.visualize.Color._
``````

The data can be grouped in two ways to produce bar charts:

``````val chart = BarChartGrouped[String, Int, Double, Map[(String, Int), Double], String](
() => sales,
title = Some("fruit sales"),
colorOf = (label: String, year: Int) => year match {
case 2011 => red
case 2012 => blue
}
)
// chart: axle.visualize.BarChartGrouped[String,Int,Double,Map[(String, Int),Double],String] = BarChartGrouped(<function0>,true,700,600,50,0.8,20,50,80,Some(fruit sales),None,Courier New,12,Palatino,20,None,None,None,Some(UnittedQuantity(36.0,UnitOfMeasurement(degree,°,Some(http://en.wikipedia.org/wiki/Degree_(angle))))),<function2>,<function2>,<function2>)
``````

Create the SVG

``````import axle.web._
// import axle.web._

svg(chart, "barchart1.svg")
``````

Or alternatively

``````val chart = BarChartGrouped[Int, String, Double, Map[(Int, String), Double], String](
() => sales map { case (k, v) => (k._2, k._1) -> v},
colorOf = (year: Int, label: String) => label match {
case "apple" => red
case "banana" => yellow
case "coconut" => brown
},
title = Some("fruit sales")
)
// chart: axle.visualize.BarChartGrouped[Int,String,Double,Map[(Int, String),Double],String] = BarChartGrouped(<function0>,true,700,600,50,0.8,20,50,80,Some(fruit sales),None,Courier New,12,Palatino,20,None,None,None,Some(UnittedQuantity(36.0,UnitOfMeasurement(degree,°,Some(http://en.wikipedia.org/wiki/Degree_(angle))))),<function2>,<function2>,<function2>)
``````

Create the second SVG

``````import axle.web._
// import axle.web._

svg(chart, "barchart2.svg")
``````

## Animation

This example keeps the “bar” value steady at 1.0 while assigning a new random Double (between 0 and 1) to “foo” every second.

Imports

``````import axle.visualize._
import spire.implicits._
import scala.util.Random.nextDouble
import axle.jung._
import axle.quanta.Time
import edu.uci.ics.jung.graph.DirectedSparseGraph
import monix.reactive._
import monix.execution.Scheduler.Implicits.global
import axle.reactive.intervalScan
import axle.reactive.CurrentValueSubscriber
import axle.awt.play
``````

``````val groups = Vector("foo", "bar")
// groups: scala.collection.immutable.Vector[String] = Vector(foo, bar)

val initial = Map("foo" -> 1d, "bar" -> 1d)
// initial: scala.collection.immutable.Map[String,Double] = Map(foo -> 1.0, bar -> 1.0)

val tick = (previous: Map[String, Double]) => previous + ("foo" -> nextDouble)
// tick: Map[String,Double] => scala.collection.immutable.Map[String,Double] = <function1>

implicit val timeConverter = {
import axle.algebra.modules.doubleRationalModule
Time.converterGraphK2[Double, DirectedSparseGraph]
}
// timeConverter: axle.quanta.UnitConverterGraph[axle.quanta.Time,Double,edu.uci.ics.jung.graph.DirectedSparseGraph[axle.quanta.UnitOfMeasurement[axle.quanta.Time],Double => Double]] with axle.quanta.TimeConverter[Double] = axle.quanta.Time\$\$anon\$1@21ec06b2

import timeConverter.second
// import timeConverter.second

val dataUpdates: Observable[Map[String, Double]] = intervalScan(initial, tick, 1d *: second)
``````

Create `CurrentValueSubscriber`, which will be used by the `BarChart` to get the latest value

``````val cvSub = new CurrentValueSubscriber[Map[String, Double]]()

val chart = BarChart[String, Double, Map[String, Double], String](
() => cvSub.currentValue.getOrElse(initial),
title = Some("random")
)
``````

Animate

``````val paintCancellable = play(chart, dataUpdates)
``````

Tear down the resources

``````paintCancellable.cancel()
cvCancellable.cancel()
``````