Interactive Charts
Open-source data visualisations
I'm sharing some inspiring visualisations I explored with workshop participants at a datavis workshop in Ghana this week. They provide an overview of popular software packages for interactive graphs.
See here for the course materials.
Overview
For other R libraries, see leaflet, htmlwidgets, plotly and useful tutorials on data visualisation in R at flowingdata.com.
Many of the packages below require that you have Rtools installed in addition to base R. I also recommend using RStudio as a front end.
A. The rCharts package
The rCharts package allows you to create, customize and publish interactive javascript visualizations from R using a lattice style plotting interface.
To get started, open R and install and load the package as follows.
library(devtools)
install_github('ramnathv/rCharts')
Then you can start exploring the examples using pre-loaded datasets or your own data. For more examples, check out the rCharts gallery.
A.1. Population pyramid
library(rCharts)
source('http://klein.uk/R/Viz/pyramids.R')
## Select population counts for Qatar in 2014
dat <- getAgeTable2(country='QA', year=2014)
head(dat)
| Year | Age | total | Male | Female | percent | pctMale | pctFemale | sexratio | ord | |
|---|---|---|---|---|---|---|---|---|---|---|
| 2 | 2014 | 0-4 | 101272 | 51253 | 50019 | 4.8 | 3.1 | 10.3 | 102.5 | 1 | 
| 3 | 2014 | 5-9 | 88869 | 45308 | 43561 | 4.2 | 2.8 | 9.0 | 104.0 | 2 | 
| 4 | 2014 | 10-14 | 74976 | 37916 | 37060 | 3.5 | 2.3 | 7.6 | 102.3 | 3 | 
| 5 | 2014 | 15-19 | 87906 | 55349 | 32557 | 4.1 | 3.4 | 6.7 | 170.0 | 4 | 
| 6 | 2014 | 20-24 | 196261 | 152929 | 43332 | 9.2 | 9.3 | 8.9 | 352.9 | 5 | 
| 7 | 2014 | 25-29 | 322775 | 259540 | 63235 | 15.2 | 15.8 | 13.0 | 410.4 | 6 | 
n1 <- nPyramid(dat, colors = c('darkred', 'silver'))
n1
A.2. Data table
## Load data
SchoolsGroup <- read.csv("https://raw.github.com/patilv/rChartsTutorials/master/SchoolsGroup.csv")
head(SchoolsGroup)
| X | Group.1 | Group.2 | Group.3 | Group.4 | 
|---|---|---|---|---|
| 1 | Texas | Cincinnati | Kentucky | Bowling Green | 
| 2 | Ohio State | Memphis | Louisville | William & Mary | 
| 3 | Michigan | Air Force | South Carolina | Montana | 
| 4 | Alabama | South Florida | Minnesota | North Dakota | 
| 5 | Florida | Boise State | Washington | South Alabama | 
| 6 | Texas A&M | New Mexico | North Carolina | Maine | 
## Load styles
tab2 <- dTable(SchoolsGroup[,-1], sPaginationType = "full_numbers")
tab2$templates$script <- "https://timelyportfolio.github.io/rCharts_dataTable/chart_customsort.html" 
## Set column names
tab2$params$table$aoColumns =
  list(
    list(sType = "string_ignore_null", sTitle = "Group 1"),
    list(sType = "string_ignore_null", sTitle = "Group 2"),
    list(sType = "string_ignore_null", sTitle = "Group 3"),
    list(sType = "string_ignore_null", sTitle = "Group 4")
  )
## Produce data table
n1 <- tab2
n1
 
B. The googleVis package
The googleVis package provides an interface to Google Charts API, allowing users to create interactive charts based on R data frames.
B.1. Tree map
## Load the googleVis library
library(googleVis)
## Inspect data
head(Regions)
| Region | Parent | Val | Fac | 
|---|---|---|---|
| Global | NA | 10 | 2 | 
| America | Global | 2 | 4 | 
| Europe | Global | 99 | 11 | 
| Asia | Global | 10 | 8 | 
| France | Europe | 71 | 2 | 
| Sweden | Europe | 89 | 3 | 
## Plot
Tree <- gvisTreeMap(Regions,  
                    "Region", "Parent", 
                    "Val", "Fac", 
                    options=list(fontSize=16))
plot(Tree)
B.2. Sankey chart
datSK <- data.frame(From=c(rep("A",3), rep("B", 3)),
                    To=c(rep(c("X", "Y", "Z"),2)),
                    Weight=c(5,7,6,2,9,4))
head(datSK)
| From | To | Weight | 
|---|---|---|
| A | X | 5 | 
| A | Y | 7 | 
| A | Z | 6 | 
| B | X | 2 | 
| B | Y | 9 | 
| B | Z | 4 | 
Sankey <- gvisSankey(datSK, from="From", to="To", weight="Weight",
                     options=list(
                       sankey="{link: {color: { fill: '#d799ae' } },
                            node: { color: { fill: '#a61d4c' },
                            label: { color: '#871b47' } }}"))
plot(Sankey)
B.3. Calendar chart
head(Cairo)
| Date | Temp | |
|---|---|---|
| 2558 | 2002-01-01 | 13.61111 | 
| 2559 | 2002-01-02 | 15.16667 | 
| 2560 | 2002-01-03 | 12.00000 | 
| 2561 | 2002-01-04 | 12.00000 | 
| 2562 | 2002-01-05 | 13.05556 | 
| 2563 | 2002-01-06 | 10.05556 | 
Cal <- gvisCalendar(Cairo, 
                    datevar="Date", 
                    numvar="Temp",
                    options=list(
                      title="Daily temperature in Cairo",
                      height=320,
                      calendar="{yearLabel: { fontName: 'Times-Roman',
                               fontSize: 32, color: '#1A8763', bold: true},
                               cellSize: 10,
                               cellColor: { stroke: 'red', strokeOpacity: 0.2 },
                               focusedCellColor: {stroke:'red'}}")
)
plot(Cal)
B.4. Pie chart
head(CityPopularity)
| City | Popularity | 
|---|---|
| New York | 200 | 
| Boston | 300 | 
| Miami | 400 | 
| Chicago | 500 | 
| Los Angeles | 600 | 
| Houston | 700 | 
Pie <- gvisPieChart(CityPopularity)
plot(Pie)
B.5. Geo chart
head(Exports)
| Country | Profit | Online | 
|---|---|---|
| Germany | 3 | TRUE | 
| Brazil | 4 | FALSE | 
| United States | 5 | TRUE | 
| France | 4 | TRUE | 
| Hungary | 3 | FALSE | 
| India | 2 | TRUE | 
Geo=gvisGeoChart(Exports, locationvar="Country", 
                 colorvar="Profit",
                 options=list(projection="kavrayskiy-vii"))
plot(Geo)
B.6. Motion chart
head(Fruits)
| Fruit | Year | Location | Sales | Expenses | Profit | Date | 
|---|---|---|---|---|---|---|
| Apples | 2008 | West | 98 | 78 | 20 | 2008-12-31 | 
| Apples | 2009 | West | 111 | 79 | 32 | 2009-12-31 | 
| Apples | 2010 | West | 89 | 76 | 13 | 2010-12-31 | 
| Oranges | 2008 | East | 96 | 81 | 15 | 2008-12-31 | 
| Bananas | 2008 | East | 85 | 76 | 9 | 2008-12-31 | 
| Oranges | 2009 | East | 93 | 80 | 13 | 2009-12-31 | 
M <- gvisMotionChart(Fruits, 'Fruit', 'Year',
         options=list(width=400, height=350))
plot(M)
C. The rMaps package
The rMaps package makes it easy to create, customize and share interactive maps from R, with a few lines of code. It supports several javascript based mapping libraries like Leaflet, DataMaps and Crosslet.
To get started, open R and install and load the package as follows.
library(devtools)
install_github('ramnathv/rMaps')
C.1. Leaflet heat maps
## 1. Create map
library(rMaps)
L2 <- Leaflet$new()
L2$setView(c(29.7632836,  -95.3632715), 15)
L2$tileLayer(provider = "MapQuestOpen.OSM")
L2
## 2. Get data
data(crime, package="ggmap")
library(plyr)
crime_dat <- ddply(crime, .(lat, lon), summarise, count = length(address))
head(crime_dat)
| lat | lon | count | 
|---|---|---|
| 27.50711 | -99.50555 | 1 | 
| 29.48361 | -95.06187 | 10 | 
| 29.52218 | -95.05838 | 5 | 
| 29.52218 | -95.05838 | 8 | 
| 29.52367 | -95.05804 | 2 | 
| 29.53743 | -95.11919 | 1 | 
## 3. Transform to json format
crime_dat <- rCharts::toJSONArray2(na.omit(crime_dat), json = F, names = F)
## 4. Add leaflet-heat plugin. 
L2$addAssets(jshead = c(
  "https://leaflet.github.io/Leaflet.heat/dist/leaflet-heat.js"
))
## 5. Add javascript to modify underlying chart
L2$setTemplate(afterScript = sprintf("<script> var addressPoints = %s
  var heat = L.heatLayer(addressPoints).addTo(map) </script>", 
  rjson::toJSON(crime_dat)
))
L2
C.2. Animated choropleths
## Get data
library(Quandl)
vcData <- Quandl("FBI_UCR/USCRIME_TYPE_VIOLENTCRIMERATE")
head(vcData[,1:6])
| Year | Alabama | Alaska | Arizona | Arkansas | California | 
|---|---|---|---|---|---|
| 2010-12-31 | 377.8 | 638.8 | 408.1 | 505.3 | 440.6 | 
| 2009-12-31 | 450.1 | 633.4 | 426.5 | 515.8 | 473.3 | 
| 2008-12-31 | 451.3 | 650.9 | 481.2 | 504.6 | 506.2 | 
| 2007-12-31 | 447.9 | 662.3 | 514.5 | 532.6 | 522.6 | 
| 2006-12-31 | 425.2 | 686.8 | 545.4 | 557.2 | 533.3 | 
| 2005-12-31 | 433.0 | 632.0 | 512.0 | 528.0 | 526.0 | 
## Reshape data
library(reshape2)
datm <- melt(vcData, 'Year', 
  variable.name = 'State',
  value.name = 'Crime'
)
datm <- subset(na.omit(datm), 
  !(State %in% c("United States", "District of Columbia"))
)
## Discretize crime rates
datm2 <- transform(datm,
  State = state.abb[match(as.character(State), state.name)],
  fillKey = cut(Crime, quantile(Crime, seq(0, 1, 1/5)), labels = LETTERS[1:5]),
  Year = as.numeric(substr(Year, 1, 4))
)
## Associate fill colors
fills = setNames(
  c(RColorBrewer::brewer.pal(5, 'YlOrRd'), 'white'),
  c(LETTERS[1:5], 'defaultFill')
)
## Create payload for data maps
library(plyr); library(rMaps)
dat2 <- dlply(na.omit(datm2), "Year", function(x){
  y = rCharts::toJSONArray2(x, json = F)
  names(y) = lapply(y, '[[', 'State')
  return(y)
})
## Create simple choropleth
options(rcharts.cdn = TRUE)
map <- Datamaps$new()
map$set(
  dom = 'chart_1',
  scope = 'usa',
  fills = fills,
  data = dat2[[46]],
  legend = TRUE,
  labels = TRUE
)
map
 
## Animated choropleth
map2 = map$copy()
map2$set(
  bodyattrs = "ng-app ng-controller='rChartsCtrl'"
)
map2$addAssets(
  jshead = "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.1/angular.min.js"
)
map2$setTemplate(chartDiv = "
  <div class='container'>
    <input id='slider' type='range' min=2005 max=2010 ng-model='year' width=200>
    <span ng-bind='year'></span>
    <div id='' class='rChart datamaps'></div>  
  </div>
  <script>
    function rChartsCtrl($scope){
      $scope.year = 2005;
      $scope.$watch('year', function(newYear){
        map.updateChoropleth(chartParams.newData[newYear]);
      })
    }
  </script>"
)
map2$set(newData = dat2)
map2
Comments
comments powered by Disqus