1
votes

For data communication process between languages, I need to have a function which convert a R's data.frame with row and column names to nested named lists (colnames -> rownames -> values). See example below. The ultimate goal is to convert it in JSON.

Example of a data.frame input:

df <- data.frame(A=c(0.1, 0.2, 0.15), B=c(1.4, 1.4, 1.6), C=c(459, 486, 499))
row.names(df) <- c('Toy99', 'Mit99', 'Mit00')
         A   B   C
Toy99 0.10 1.4 459
Mit99 0.20 1.4 486
Mit00 0.15 1.6 499

Expected output:

> jsonlite::toJSON(convertToJsonpy(df), pretty = TRUE, auto_unbox = TRUE)
{
  "A": {
    "Toy99": 0.1,
    "Mit99": 0.2,
    "Mit00": 0.15
  },
  "B": {
    "Toy99": 1.4,
    "Mit99": 1.4,
    "Mit00": 1.6
  },
  "C": {
    "Toy99": 459,
    "Mit99": 486,
    "Mit00": 499
  }
}

I have this function so far but it's slow with big data.frames:

convertToJsonpy <- function(df) {
  res = list()
  for (col_label in colnames(df)) {
    res_row = list()
    for (row_label in row.names(df)) {
      res_row[[row_label]] <- df[row_label, col_label]
    }
    res[[col_label]] <- res_row
  }
  return(res)
}

Is there an another solution using Dplyr, Purrr, etc?
Thank you

1

1 Answers

3
votes

Using lapply you can convert the data.frame to the correct list structure

lst <- lapply( df, function(x) { 
  names(x) <- row.names( df )
  as.list( x )
})

str( lst )
# List of 3
# $ A:List of 3
# ..$ Toy99: num 0.1
# ..$ Mit99: num 0.2
# ..$ Mit00: num 0.15
# $ B:List of 3
# ..$ Toy99: num 1.4
# ..$ Mit99: num 1.4
# ..$ Mit00: num 1.6
# $ C:List of 3
# ..$ Toy99: num 459
# ..$ Mit99: num 486
# ..$ Mit00: num 499

Then there are a couple of json libraries you can use

jsonify::pretty_json(
  jsonify::to_json( lst, unbox = T )
)
# {
#   "A": {
#     "Toy99": 0.1,
#     "Mit99": 0.2,
#     "Mit00": 0.15
#   },
#   "B": {
#     "Toy99": 1.4,
#     "Mit99": 1.4,
#     "Mit00": 1.6
#   },
#   "C": {
#     "Toy99": 459.0,
#     "Mit99": 486.0,
#     "Mit00": 499.0
#   }
# }

jsonlite::toJSON( lst, pretty = T, auto_unbox = T )
# {
#   "A": {
#     "Toy99": 0.1,
#     "Mit99": 0.2,
#     "Mit00": 0.15
#   },
#   "B": {
#     "Toy99": 1.4,
#     "Mit99": 1.4,
#     "Mit00": 1.6
#   },
#   "C": {
#     "Toy99": 459,
#     "Mit99": 486,
#     "Mit00": 499
#   }
# }