6

I have some hierarchical data, e.g.,

> library(dplyr)
> df <- data_frame(id = 1:6, parent_id = c(NA, 1, 1, 2, 2, 5))
> df
Source: local data frame [6 x 2]

     id parent_id
  (int)     (dbl)
1     1        NA
2     2         1
3     3         1
4     4         2
5     5         2
6     6         5

I would like to plot the tree in a "top down" view through a circle packing plot: http://bl.ocks.org/mbostock/4063530

circle packing plot

The above link is for a d3 library. Is there an equivalent that allows me to make such a plot in ggplot2?

(I want this plot in a shiny app, which does support d3, but I haven't used d3 before and am unsure about the learning curve. If d3 is the obvious choice, I will try to get that working instead. Thanks.)

Rorschach
  • 31,301
  • 5
  • 78
  • 129
Eric
  • 829
  • 1
  • 8
  • 15

1 Answers1

12

There were two steps: (1) aggregate the data, then (2) convert to json. After that, all the javascript has been written in that example page, so you can just plug in the resulting json data.

Since the aggregated data should have a similar structure to a treemap, we can use the treemap package to do the aggregation (could also use a loop with successive aggregation). Then, d3treeR (from github) is used to convert the treemap data to a nested list, and jsonlite to convert the list to json.

I'm using some example data GNI2010, found in the d3treeR package. You can see all of the source files on plunker.

library(treemap)
library(d3treeR)  # devtools::install_github("timelyportfolio/d3treeR")
library(data.tree)
library(jsonlite)

## Get treemap data using package treemap
## Using example data GNI2010 from d3treeR package
data(GNI2010)

## aggregate by these: continent, iso3,
## size by population, and color by GNI
indexList <- c('continent', 'iso3')  
treedat <- treemap(GNI2010, index=indexList, vSize='population', vColor='GNI',
               type="value", fun.aggregate = "sum",
               palette = 'RdYlBu')
treedat <- treedat$tm  # pull out the data

## Use d3treeR to convert to nested list structure
## Call the root node 'flare' so we can just plug it into the example
res <- d3treeR:::convert_treemap(treedat, rootname="flare")

## Convert to JSON using jsonlite::toJSON
json <- toJSON(res, auto_unbox = TRUE)

## Save the json to a directory with the example index.html
writeLines(json, "d3circle/flare.json")

I also replaced the source line in the example index.html to

  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>

Then fire up the index.html and you should see enter image description here

To create the shiny bindings should be doable using htmlwidgets and following some examples (the d3treeR source has some). Note that certain things aren't working, like the coloring. The json that gets stored here actually contains a lot of information about the nodes (all the data aggregated using the treemap) that you could leverage in the figure.

Rorschach
  • 31,301
  • 5
  • 78
  • 129
  • 1
    Beautiful, thank you! I'm amazed at how quickly you figured this out. I've reproduced your answer up to (but excluding) the htmlwidgets point without problems. The only issues I had (in case it helps anyone else): (1) I had to run `data(GNI2010)` first. (2) Initially index.html was loading a blank page, which was solved by starting a local server as described in [this stackoverflow answer](http://stackoverflow.com/a/23118676/2530226). – Eric Nov 11 '15 at 06:06
  • great! I would have liked to go further and make the htmlwidget, but I don't have experience with that. Although, looking at the code https://github.com/timelyportfolio/d3treeR/blob/master/R/d3tree.R#L122 makes it look quite feasible. – Rorschach Nov 11 '15 at 06:12
  • 1
    Thanks so much for this answer. Also, you might want to have a look at `data.tree` https://github.com/gluc/data.tree for aggregation and tree-manipulation. I have found it to be extremely helpful. – timelyportfolio Jan 05 '16 at 14:50
  • What is object "GNI2010"? R is not finding it (in the proposed solution) – user3245256 Jul 11 '17 at 14:08
  • @user3245256 I believe that needs to be loaded, see first comment – Rorschach Jul 11 '17 at 14:12
  • data(GNI2010) is not running. I am getting an error: In data(GNI2010) : data set ‘GNI2010’ not found – user3245256 Jul 12 '17 at 14:47
  • Ah, I think it's outdated. Now one needs to run data(GNI2014) – user3245256 Jul 12 '17 at 14:49
  • Still cannot reproduce the map. I got a mosaic plot - a rectangle in which each country is a rectangle, according to its size. But no circles. – user3245256 Jul 12 '17 at 14:51