Note: This package was forked from Yihui Xie and is based on the last release of Baidu Echarts2 (v2.2.7). The documentation here always reflects the latest development version of recharts on Github. The package recharts2 that is based on Echarts3 is still under development.

To install the package:

if (!require(devtools)) library(devtools)
install_github("madlogos/recharts")

1 Knowledge Map of the Guidance

  1. Base Plots
    1. Mono-coordinate System
      1. Cartesian Coordinate System
        1. Scatter/Bubble Plot
        2. Bar/Column Chart
        3. Line/Area Chart
        4. Candlestick/K Chart
        5. Event River Chart
      2. Others
        1. Force Chart
        2. Chord Chart
        3. Word Cloud
        4. Venn Chart
        5. Heatmap
    2. Multi-coordinate System
      1. Polar Coordinate System
        1. Pie/Ring/Rose Chart
        2. Funnel/Pyramid Chart
        3. Radar Chart
        4. Gauge Chart
      2. Others
        1. Map
        2. Tree Chart
        3. Treemap
  2. Mixed Plots
  3. Axis/Widget Configuration
    1. Tune Series
      1. setSeries
    2. Axis/Grid
      1. setAxis
      2. setPolar
      3. setGrid
    3. Graph Elements
      1. addMarkLine
      2. addMarkPoint
    4. Widgets
      1. setTitle
      2. setLegend
      3. setTimeline
      4. setToolbox
      5. setDataRange
      6. setDataZoom
      7. setRoam
    5. Feature Lists
      1. aesStyle
  4. Aesthetic Configuration
    1. setTooltip
    2. setSymbols
    3. setTheme
  5. Customization

2 Hello World

The R package recharts provides an interface to the JavaScript library ECharts2 for data visualization. The goal of this package is to make it easy to create charts with only a few lines of R code. R users should be able to get started with ECharts without having to know HTML or JavaScript, although advanced users will benefit from their knowledge of JavaScript. Here is an example of a scatterplot that shows the basic syntax of this package:

library(recharts)
echartr(iris, Sepal.Length, Sepal.Width, series = Species)

You can always call browseVignettes("recharts") to view the manual locally.

The recharts package was built on top of htmlwidgets, which can save us a lot of time on managing JavaScript dependencies and dealing with different types of output documents such as R Markdown and Shiny. You just create a chart, and we will take care of the rest of things when the chart is renderd in R Markdown, Shiny, or the R console / RStudio.

The main function in this package is the echartr() function (an S3 generic function), and we want to make it smart enough to deal with different types of R data automatically. For example, when a data frame is passed to echart(), and the x/y variables are numeric, it should automatically figure out that you probably need a scatterplot, and the axes will be automatically generated. Of course, you can also override the automatic guess.

3 Quick Start

Follow the steps below to make a plot yourself.

3.1 Data

Always start from data itself. Let’s use mtcars in the package datasets. You can type ?mtcars to read the instruction.

head(mtcars)
##                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
## Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
## Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

We want to know the relationship between wt (weight) and mpg (miles per gallon), a scatterplot is a good fit. It requires x and y variables of numeric.

3.2 Core Plot

Use echartr to build the basic chart.

echartr(mtcars, wt, mpg)

The grammar of echartr is

## function (data, x = NULL, y = NULL, series = NULL, weight = NULL, 
##     facet = NULL, t = NULL, lat = NULL, lng = NULL, type = "auto", 
##     subtype = NULL, elementId = NULL, ...)

3.2.1 Arguments

Arg Interpretation

data

source data in the form of data.frame

x

Independent variable(s). One or more columns of data. Could be time, numeric or characters.

  • In Cartesian coordinate system charts, x is linked with x-axis
  • In polar coordinate system charts, x var1 is linked with polar-axis, and x var2 is data series (linked with legends)
  • In other chart types, mono-coordinate system charts refer to Cartesian coordinat system examples, while multi-coordinates system charts refer to polar system examples.

y

dependent variable(s). One or more columns of data. Always numeric.

series

series variable. A column of data which is treated as factors.

weight

weight variable used in bubble, bar/column, line/area chart, linking with the size of graph elements.

facet

facet variable to devide the canvas into facets. Only applicable for multi-coordinate system charts (e.g., pie charts).

t

time variable. If t is assigned, a timeline widget will display.

lat

latitude variable for map/heatmap.

lng

longitude variable for map/heatmap.

type

chart type. Default ‘auto’. type as a vector is linked with series, while as a list is linked with facet.

subtype

chart subtype. Default NULL. subtype as a vector is also linked with series, while as a list is linked with facet.

3.2.2 Supported Chart Types

echartr now supports the following types (the regex patterns in ‘name’ column, case insensitive). The ‘type’ column lists chart type names supported by Echarts2.

knitr::kable(recharts:::validChartTypes[,c(1:3,5)])
id name type misc
1 ^(scatter|point)$ scatter
2 ^(bubble)$ scatter bubble
3 ^(bar|hbar)$ bar flip
4 ^(vbar|column)$ bar
5 ^(histogram|hist)$ hist
6 ^(line)$ line
7 ^(curve)$ line smooth
8 ^(area)$ line fill
9 ^(wave)$ line fill_smooth
10 ^(map_world|world_map)$ map world
11 ^(map_china|china_map)$ map china
12 ^(map_world_multi|world_map_multi)$ map world_multi
13 ^(map_china_multi|china_map_multi)$ map china_multi
14 ^(map)$ map geojson
15 ^(k|candlestick)$ k
16 ^(pie)$ pie
17 ^(ring)$ pie ring
18 ^(rose)$ pie rose
19 ^(chord)$ chord
20 ^(force|force_curve)$ force
21 ^(force_line)$ force line
22 ^(funnel)$ funnel
23 ^(pyramid)$ funnel ascending
24 ^(tree|vtree|tree_vertical)$ tree
25 ^(htree|tree_horizontal)$ tree horizontal
26 ^(tree_inv|vtree_inv|tree_vertical_inv)$ tree inv
27 ^(htree_inv|tree_horizontal_inv)$ tree horizontal_inv
28 ^(treemap)$ treemap
29 ^(wordcloud)$ wordCloud
30 ^(heatmap)$ heatmap
31 ^(radar|spider|star)$ radar
32 ^(gauge|dashboard)$ gauge
33 ^(eventriver)$ eventRiver
34 ^(venn)$ venn

You assign data and x, y, then echartr automatically processes the data using recharts:::series_scatter function.

If series is assigned, a series-specfic scatterplot is shown.

echartr(mtcars, wt, mpg, factor(am, labels=c('Automatic', 'Manual')))

If weight is assigned and type is set bubble, a bubble chart is displayed.

echartr(mtcars, wt, mpg, am, weight=gear, type='bubble')
## Warning in split_indices(.group, .n): '.Random.seed' is not an integer
## vector but of type 'NULL', so ignored

3.2.3 Special Notes

3.2.3.1 Param List

The input param list could be

  • symbols: wt, mpg or even as complicated as factor(am, labels=c('Automatic', 'Mannual'))
  • characters: 'wt', 'mpg'
  • formulas: ~wt, ~mpg

3.2.3.2 Data Requirements

Data must be a data.frame. The data series and timeline will display in the original order of series and t, so you should sort the data.frame before making charts so as to make sure the display order is exactly what you want.

When it comes to timeline (t), you must be very cautious. All the combination sets of x, y, series, weight should be exactly equal across all the levels of t. Otherwise you will find confusious overlap of graphs across timeline.

3.2.3.3 Type And Subtype

3.2.3.3.1 Mixed Types

recharts supports mixed chart types in some cases, e.g., bar and line.

By now, recharts only supports the following misure of types: - Cartesian coordinate charts: scatterplot/bubble, bar/column, line/area charts - Polar coordinate charts: funnel, pie/ring charts - Others: force, chord charts

d <- data.table::dcast(mtcars, carb+gear~., mean, value.var='mpg')
names(d)[3] <- 'mean.mpg'
d$carb <- as.character(d$carb)
echartr(d, carb, "mean.mpg", gear, type=c('vbar', 'vbar', 'line')) %>% 
    setSymbols('emptycircle')

Or mixed subtypes. Refer to ‘subtype’ column in recharts:::validChartTypes. You can assign combined subtypes using ‘+’, ’_‘or’|‘, e.g., ’stack+smooth’ to simultaneously render the line chart stacked and smooth.

echartr(d, carb, mean.mpg, gear, type='line', 
        subtype=c('stack + smooth', 'stack + dotted', 'smooth + dashed')) %>%
    setSymbols('emptycircle')
3.2.3.3.2 Associating Type/Subtype with Facets

The above example shows how to associate type/subtype with series. If you want to associate type/subtype with facets, you need to wrap them in a list. Within each list, the vector of type/subtypes are associated with series, ie, list[[1]], list[[2]], … are associated with facet 1, 2, …, while list[[1]][1], list[[1]][2], … are associated with series 1, 2, …

If facet has 2 levels and series has 3 levels, it means type and subtype should have a structure of list(c(s1,s2,s3), c(s1,s2,s3)). recharts will try to supplement/cut the income params type and subtype to meet the mapping relationship.

Series/facet facet 1 facet 2 facet i
series 1 list[[1]][1] list[[2]][1] list[[i]][1]
series 2 list[[1]][2] list[[2]][2] list[[i]][2]
series j list[[1]][j] list[[2]][j] list[[i]][j]
d1 <- data.frame(x=rep(LETTERS[1:6], 4), y=abs(rnorm(24)), 
                 f=c(rep('i', 12), rep('ii', 12)), 
                 s=rep(c(rep('I', 6), rep('II', 6)), 2))
echartr(d1, x, y, s, facet=f, type='radar', 
        subtype=list(c('fill', ''), c('', 'fill')))

3.3 Modify the Plot

You can save the plot as an object and keep modifying the plot using %>%.

g = echartr(mtcars, wt, mpg, factor(am, labels=c('Automatic', 'Manual')))

3.3.1 Tune the Series

The above command made an Echarts object g containing two series: ‘Automatic’ and ‘Manual’. The data strcuture of g is:

- x
  |-- series
      |--- list 1
           |---- name: 'Automatic'
           |---- data: ...
           |---- type: 'scatter'
      |--- list 2
           |---- name: 'Manual'
           |---- data: ...
           |---- type: 'scatter'
      |--- ...
  |-- legend
  |-- xAxis
  |-- yAxis
  |-- grid  
  |-- tooltip
  |-- ...

If you want to customize the definition of the series directly, you can call the low-level function setSeries.

Let’s set ‘Manual’ series (series index 2) symbolSize 8, symbolRotate 30.

g %>% setSeries(series=2, symbolSize=8, symbolRotate=30)

3.3.2 markLine

Markline the average level of the two series.

g %>% addMarkLine(data=data.frame(type='average', name1='Avg'))

3.3.3 markPoint

Markpoint the maximum of series 1 (‘Automatic’).

g %>% addMarkPoint(series=1, data=data.frame(type='max', name='Max'))

It’s the same as

g %>% addMarkPoint(series='Automatic', data=data.frame(type='max', name='Max'))

3.3.4 Title

Add title (in red) and subtitle (with reference link to https://stat.ethz.ch/R-manual/R-devel/library/datasets/html/mtcars.html) to the chart.

link <- 'https://stat.ethz.ch/R-manual/R-devel/library/datasets/html/mtcars.html'
g %>% setTitle('wt vs mpg', paste0('[Motor Trend](', link, ')'), 
               textStyle=list(color='red'))

3.3.5 Legend

Modify the legend (in lime), and only select series 1 (‘Automatic’) at the beginning.

g %>% setLegend(selected='Automatic', textStyle=list(color='lime'))

3.3.6 Toolbox

Modify toolbox as English, and put it to the upper-right of the chart with vertical display.

Refer to vecPos() function to see how pos is defined.

g %>% setToolbox(lang='en', pos=2)

3.3.7 DataZoom

Add dataZoom (orignally there is not one).

g %>% setDataZoom()

3.3.8 Axis

Modify axes to make x- and y-axis cross at zero.

g %>% setXAxis(min=0) %>% setYAxis(min=0)

3.4 Fortify the Chart

3.4.1 Theme

Apply ‘dark’ theme to the chart. You can also apply “macarons”, “infographic”, “blue”, “dark”, “gray”, “green”, “helianthus”, “macarons2”, “mint”, “red”, “roma”, “sakura”, “shine”, and “vintage”.

Calculable is a special interation in Echarts. In other charts (e.g.,pie), it is quite efficient.

g %>% setTheme('dark', calculable=TRUE)

3.4.2 Symbols

Set symbolList for series 1 (‘Automatic’) ‘heart’ and that for series 2 (‘Manual’) ‘star6’.

g %>% setSymbols(c('heart', 'star6'))

3.5 Altogether

You can combine all the steps using a pipe chain. If you are familiar with JS, you can embed JS fragments using JS() for better effects.

g %>% setSeries(series=2, symbolSize=8, symbolRotate=30) %>% 
    addMarkLine(data=data.frame(type='average', name1='Avg')) %>%
    addMarkPoint(series=1, data=data.frame(type='max', name='Max')) %>%
    setTitle('wt vs mpg', paste0('[Motor Trend](', link, ')'), 
               textStyle=list(color='red')) %>%
    setLegend(selected='Automatic', textStyle=list(color='lime')) %>%
    setToolbox(lang='en', pos=2) %>% setDataZoom() %>% 
    setTheme('dark', calculable=TRUE) %>% setSymbols(c('heart', 'star6'))

4 Low-level API

4.1 De Novo

Given that ECharts supports so many types of charts, it may take a while for us to make echartr() really smart. With that in mind, we also provided a really low-level S3 method defined for lists. Since the main usage of ECharts is that you pass a JavaScript object to the method .setOption(), and we can construct such an object using a list in R. This low-level echart.list() method makes it possible for you to create arbitrary charts. Here is a simple example of a Chord diagram taken from http://echarts.baidu.com/doc/example/chord1.html:

chordEx1 = list(
  title = list(
    text = '测试数据',
    subtext = 'From d3.js',
    x = 'right',
    y = 'bottom'
  ),
  tooltip = list(
    trigger = 'item',
    formatter = JS('function(params) {
      if (params.indicator2) { // is edge
        return params.value.weight;
      } else {// is node
        return params.name
      }
    }')
  ),
  toolbox = list(
    show = TRUE,
    feature = list(
      restore = list(show = TRUE),
      magicType = list(show = TRUE, type = c('force', 'chord')),
      saveAsImage = list(show = TRUE)
    )
  ),
  legend = list(
    x = 'left',
    data = c('group1', 'group2', 'group3', 'group4')
  ),
  series = list(
    list(
      type = 'chord',
      sort = 'ascending',
      sortSub = 'descending',
      showScale = TRUE,
      showScaleText = TRUE,
      data = list(
        list(name = 'group1'),
        list(name = 'group2'),
        list(name = 'group3'),
        list(name = 'group4')
      ),
      itemStyle = list(
        normal = list(
          label = list(show = FALSE)
        )
      ),
      matrix = rbind(
        c(11975,  5871, 8916, 2868),
        c( 1951, 10048, 2060, 6171),
        c( 8010, 16145, 8090, 8045),
        c( 1013,   990,  940, 6907)
      )
    )
  )
)

echart(chordEx1)

It is exactly the same as

mat <- as.data.frame(rbind(
        c(11975,  5871, 8916, 2868),
        c( 1951, 10048, 2060, 6171),
        c( 8010, 16145, 8090, 8045),
        c( 1013,   990,  940, 6907)
      ))
names(mat) <- c("group1", "group2", "group3", "group4")
mat$name <- names(mat)

echartr(mat, x=name, y=c(group1, group2, group3, group4), type="chord", 
        subtype='ribbon + asc + descsub + hidelab + scaletext') %>%
        setTitle("测试数据", subtitle="From d3.js", pos=5)

Apparently, all we did was to translate the JavaScript object in the original example into R. Note we translated the function tooltip.fomatter using the JS() function in htmlwidgets. All other objects can be mapped naturally to R.

4.2 Modify the Echarts Object

We can also yield an echarts object using echartr and then modify the object directly as we do to a S3 list, if we are familiar with echarts data structure.

The following is the structure of the object g we producted by echartr(mtcars, wt, mpg, factor(am, labels=c('Automatic', 'Mannual'))).

enquote(g)
## quote(list(x = list(series = list(list(name = "Automatic", type = "scatter", 
##     data = list(list(3.215, 21.4), list(3.44, 18.7), list(3.46, 
##         18.1), list(3.57, 14.3), list(3.19, 24.4), list(3.15, 
##         22.8), list(3.44, 19.2), list(3.44, 17.8), list(4.07, 
##         16.4), list(3.73, 17.3), list(3.78, 15.2), list(5.25, 
##         10.4), list(5.424, 10.4), list(5.345, 14.7), list(2.465, 
##         21.5), list(3.52, 15.5), list(3.435, 15.2), list(3.84, 
##         13.3), list(3.845, 19.2))), list(name = "Manual", type = "scatter", 
##     data = list(list(2.62, 21), list(2.875, 21), list(2.32, 22.8), 
##         list(2.2, 32.4), list(1.615, 30.4), list(1.835, 33.9), 
##         list(1.935, 27.3), list(2.14, 26), list(1.513, 30.4), 
##         list(3.17, 15.8), list(2.77, 19.7), list(3.57, 15), list(
##             2.78, 21.4)))), legend = list(show = TRUE, data = list(
##     "Automatic", "Manual"), x = "left", y = "top", orient = "horizontal"), 
##     yAxis = list(list(type = "value", show = TRUE, position = "left", 
##         name = "mpg", nameLocation = "end", boundaryGap = c(0, 
##         0), scale = TRUE, axisLine = list(show = TRUE, onZero = FALSE), 
##         axisTick = list(show = FALSE), axisLabel = list(show = TRUE), 
##         splitLine = list(show = TRUE), splitArea = list(show = FALSE))), 
##     xAxis = list(list(type = "value", show = TRUE, position = "bottom", 
##         name = "wt", nameLocation = "end", boundaryGap = c(0, 
##         0), scale = TRUE, axisLine = list(show = TRUE, onZero = FALSE), 
##         axisTick = list(show = FALSE), axisLabel = list(show = TRUE), 
##         splitLine = list(show = TRUE), splitArea = list(show = FALSE))), 
##     tooltip = list(show = TRUE, trigger = "axis", axisPointer = list(
##         type = "cross", crossStyle = list(type = "dashed"), lineStyle = list(
##             type = "solid", width = 1), shadowStyle = list(color = "rgba(150,150,150,0.3)", 
##             width = "auto", type = "default")), textStyle = list(
##         color = "#fff"), formatter = "function (params) {\n    var i;\n    var text = params.value[0];\n    if (params.seriesName === null || params.seriesName === \"\"){\n        if (params.value.length > 1) {\n            for (i = 1; i < params.value.length; i++){\n                text += \" ,    \" + params.value[i];\n            }\n            return text;\n        } else {\n            return params.name + \" : \" + text;\n        }\n    } else {\n        if (params.value.length > 1) {\n            text = params.seriesName + \" :<br/>\" + text;\n            for (i = 1; i < params.value.length; i++) {\n                text += \" ,    \" + params.value[i];\n            }\n            return text;\n        } else {\n            return params.seriesName + \" :<br/>\"\n            + params.name + \" : \" + text;\n        }\n    }\n    }", 
##         islandFormatter = "{a} < br/>{b} : {c}", enterable = FALSE, 
##         showDelay = 20, hideDelay = 100, transitionDuration = 0.4, 
##         backgroundColor = "rgba(0,0,0,0.7)", borderColor = "#333", 
##         borderWidth = 0, borderRadius = 4), toolbox = list(show = TRUE, 
##         feature = list(mark = list(show = TRUE), dataZoom = list(
##             show = TRUE), dataView = list(show = TRUE, readOnly = FALSE), 
##             magicType = list(show = FALSE), restore = list(show = TRUE), 
##             saveAsImage = list(show = TRUE)), x = "right", y = "top", 
##         orient = "horizontal")), width = NULL, height = NULL, 
##     sizingPolicy = list(defaultWidth = NULL, defaultHeight = NULL, 
##         padding = NULL, viewer = list(defaultWidth = NULL, defaultHeight = NULL, 
##             padding = NULL, fill = TRUE, suppress = FALSE, paneHeight = NULL), 
##         browser = list(defaultWidth = NULL, defaultHeight = NULL, 
##             padding = NULL, fill = FALSE), knitr = list(defaultWidth = NULL, 
##             defaultHeight = NULL, figure = TRUE)), dependencies = NULL, 
##     elementId = NULL, preRenderHook = NULL, jsHooks = list()))

4.3 Save Echarts Object As HTML

Echarts is actually of htmlwidgets class. So you can simply call htmlwidgets::saveWidget function to save the object as HTML.

4.4 Shiny

Refer to renderEchart function to use recharts for Shiny.

library(recharts)
library(shiny)
app = shinyApp(
  ui = fluidPage(eChartOutput('myChart')),
  server = function(input, output) {
    chart = echartr(data.frame(x = rnorm(100), y = rnorm(100)), x, y)
    output$myChart = renderEChart(chart)
  }
)

if (interactive()) print(app)

5 Finale

Normally we do not want R users to specify a long list of options like that. As R users, you are more familiar with (and often work with) data structures like data frames, matrices, tables, and so on. Ideally we hope you can just pass a familiar data object, and we configure ECharts automatically for you whenever possible. We will be happy to know your feedback, and you are welcome to contribute code through Github pull requests.