Optimus
Optimus

Reputation: 1604

Custom legend in rCharts (highcharts)

I have a dataframe that looks like:

## Data
df <- data.frame(label = c("A", "B", "C", "D"), 
                 color = c("red", "red", "blue", "green"), 
                 y = c(10, 11, 12, 13))

"A" and "B" are part of the same category, while "C" and "D" are part of separate categories.

I would like to add a legend on the chart with category labels.

## Highchart without Legend

## Basic highchart
h <- rCharts:::Highcharts$new()
h$chart(type = "column")

## Highchart data:
h$series(showInLegend = FALSE, data =  rCharts::toJSONArray2(df[, c("label", "color", "y")], json = FALSE, names = TRUE))

## Highchart options:
h$xAxis(categories = unique(df$label), labels = list(rotation = 0, align = 'center', style = list(fontSize = '12px', fontFamily = 'Verdana, sans-serif')), replace = FALSE)
h$tooltip(formatter = "#! function() {return this.x + ': ' + this.y; } !#")
h$plotOptions(series = list(color = df$color), column = list(grouping = FALSE))
h  # display highchart

enter image description here

I haven't found a method that makes any sense to solve this problem.

Any help would be appreciated.

Upvotes: 2

Views: 2719

Answers (2)

jbkunst
jbkunst

Reputation: 3029

Disclaimer: I know the question says rCharts, I just want to add an alternative using highcharter package.

Like @Optimus said, the issue is add multiples series. In case you have arbitraty number of series (colors in your example) and want add it automatically you can use highcharter with allow you to add multiples series from a list of data series with the hc_add_series_list function.

library(highcharter)
library(dplyr)

df <- data_frame(label = c("A", "B", "C", "D"), 
                 color = c("red", "red", "blue", "green"), 
                 y = c(10, 11, 12, 13),
                 x = c(1:4)-1)

head(df)

series <- df %>% 
  group_by(color) %>% # each serie is from one color
  do(data = list.parse3(.)) %>% 
  ungroup() %>% 
  mutate(name = paste("I'm color", color)) %>% 
  list.parse3()

Here list.parse3 is similar to toJSONArray2.

series[[1]]

$color
[1] "blue"

$data
$data[[1]]
$data[[1]]$label
[1] "C"

$data[[1]]$color
[1] "blue"

$data[[1]]$y
[1] 12

$data[[1]]$x
[1] 2

$name
[1] "I'm color blue"

Finally:

highchart() %>% 
  hc_chart(type = "column") %>% 
  hc_add_series_list(series) %>% 
  hc_xAxis(categories = df$label) %>% 
  hc_plotOptions(column = list(grouping = FALSE))

The result will be:

result

Upvotes: 4

Optimus
Optimus

Reputation: 1604

And here's how I solved it.

Each 'category' is split into a separate series with an x value to determine its location on the graph (highcharts requires this for some reason. Without it, the graphs stack).

Here's a sample code that works:

## Highchart with Legend
## Remark: simply switching showInLegend to TRUE will not work
df$x <- c(0, 1, 2, 3) # add an index to dataframe (starting from 0)
                      # and pass it to h$series data
h <- rCharts:::Highcharts$new()
h$chart(type = "column")
h$series(name = "Category 1 (Red)", color = "red", data = rCharts::toJSONArray2(df[df$color == "red", c("label", "color", "x", "y")], json = FALSE, names = TRUE))
h$series(name = "Category 2 (Blue)", color = "blue", data = rCharts::toJSONArray2(df[df$color == "blue", c("label", "color", "x", "y")], json = FALSE, names = TRUE))
h$series(name = "Category 3 (Green)", color = "green", data =  rCharts::toJSONArray2(df[df$color == "green", c("label", "color", "x", "y")], json = FALSE, names = TRUE)) 
h$xAxis(categories = unique(df$label), labels = list(rotation = 0, align = 'center', style = list(fontSize = '12px', fontFamily = 'Verdana, sans-serif')), replace = FALSE)
h$tooltip(formatter = "#! function() {return this.x + ': ' + this.y; } !#")
h$plotOptions(series = list(color = df$color), column = list(grouping = FALSE))
h # display chart

enter image description here

I hope this helps someone else.

Upvotes: 1

Related Questions