R to JSON for D3.js and Protovis

D3.js and Protovis use the file format JSON to hold input data. In particular, the most natural format is an array of JSON objects, such as

[ { "Petal.Width" : 0.2, "Species" : "setosa" }, { "Petal.Width" : 1.3, "Species" : "versicolor" }, { "Petal.Width" : 1.8, "Species" : "virginica" } ]

There seems to be no readily available tool for transform a R data frame into a JSON array such that each row in R becomes an JSON object in the array. The rjson package actually converts a data frame into a JSON hashmap, in which each column of the data frame becomes a named array (see below).

{"Petal.Width":[0.2,1.3,1.8],"Species":["setosa","versicolor","virginica"]}

Similar question has been asked at StackOverflow and a solution proposed. The solution involves transposing the data frame before feeding to the toJSON funciton in the rjson package.

toJSON(data.frame(t(dtf)))

The solution works for data frames with character strings. However, when a data frame has numeric columns, the final result will contain problematic quotation marks around numeric values, which makes the JSON file not suitable for D3.js or Protovis (see below). This is particularly problematic when the numbers are extremely large or small, in which case scientific notation is likely used by R to format numeric values.

{"X50":{"Petal.Width":"0.2","Species":"setosa"},"X100":{"Petal.Width":"1.3","Species":"versicolor"},"X150":{"Petal.Width":"1.8","Species":"virginica"}}

To address this problem, I wrote a function that will convert a data frame directory to a JSON string.

toJSONarray <- function(dtf){
clnms <- colnames(dtf)

name.value <- function(i){
quote <- '';
if(class(dtf[, i])!='numeric'){
quote <- '"';
}

paste('"', i, '" : ', quote, dtf[,i], quote, sep='')
}

objs <- apply(sapply(clnms, name.value), 1, function(x){paste(x, collapse=', ')})
objs <- paste('{', objs, '}')

res <- paste('[', paste(objs, collapse=', '), ']')

return(res)
}

With this function, the output will work in D3.js and Protovis:

[ { "Petal.Width" : 0.2, "Species" : "setosa" }, { "Petal.Width" : 1.3, "Species" : "versicolor" }, { "Petal.Width" : 1.8, "Species" : "virginica" } ]

About these ads

10 Comments to “R to JSON for D3.js and Protovis”

  1. Great post. Here is a question. How to output the “[ { "Petal.Width" : 0.2, "Species" : "setosa" }, { "Petal.Width" : 1.3, "Species" : "versicolor" }, { "Petal.Width" : 1.8, "Species" : "virginica" } ]” into .json file and then work with d3.js live? Thanks.

  2. Thanks! I’m using .txt instead. So, we can processing data with R, then visualize with javascript. Do you have any related works done? I’m interested with this. Here is my 1st try: Test CSV (d3.js). More are coming!

  3. Thanks for your post! Your idea will help me with my googleVis package, where I currently use the RJSONIO package.

  4. Thank you – this just saved me a lot of hassle.

  5. Great, but you assume that the only necessary check is whether or not each data frame’s vector is numeric. Didn’t catch that until my data frame’s int vectors kept being converted to strings…

  6. thanks! very helpful

  7. One more comment. For some reason I get my character entries surrounded by \”word\” instead of just “word”. Suggestions on why that might be the case?

    > str(data)
    ‘data.frame': 6612 obs. of 4 variables:
    $ payee : Factor w/ 500 levels “3M PAYROLL”,..: 1 1 1 1 1 1 1 1 1 1 …
    $ amt : num 100 1590 20 4067 4091 …
    $ date : Factor w/ 212 levels “-“,”01/01/2013″,..: 210 45 169 23 66 44 95 95 173 173 …
    $ category: Factor w/ 50 levels “”,”-“,”ATM:Cash”,..: 19 41 36 42 42 42 42 42 42 42 …

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: