Преобразование кадра данных R в JSON

Привет! У меня есть кадр данных R в следующем формате:

   user_id   email      segment name
     123    [email protected]   new     a
     234    [email protected]   old     b

Как преобразовать его в JSON с желаемым результатом:

[
      {
        "user_id": "123",
        "email": "[email protected]",
        "custom_data": {
          "segment": "new"
        },
        "tags": [
          { "name": "a" }
        ]
      },
      {
        "user_id": "234",
        "email": "[email protected]",
        "custom_data": {
          "segment": "old"
        },
        "tags": [
          { "name": "b" }
        ]
      }
    ]

Я использую пакет jsonlite.


person Peter Golovatyi    schedule 26.03.2020    source источник


Ответы (1)


Использование столбцов списка со встроенными data.frames:

dat <- read.table(header=TRUE, stringsAsFactors=FALSE, text="
   user_id   email      segment name
     123    [email protected]   new     a
     234    [email protected]   old     b")
dat$custom_data <- lapply(dat$segment, function(a) data.frame(segment = a))
dat$tags <- lapply(dat$name, function(a) data.frame(name = a))
dat$segment <- dat$name <- NULL
jsonlite::toJSON(dat, pretty = TRUE)
# [
#   {
#     "user_id": 123,
#     "email": "[email protected]",
#     "custom_data": [
#       {
#         "segment": "new"
#       }
#     ],
#     "tags": [
#       {
#         "name": "a"
#       }
#     ]
#   },
#   {
#     "user_id": 234,
#     "email": "[email protected]",
#     "custom_data": [
#       {
#         "segment": "old"
#       }
#     ],
#     "tags": [
#       {
#         "name": "b"
#       }
#     ]
#   }
# ] 

Одно отличие состоит в том, что в вашем "custom_data" это просто словарь/хэш, тогда как jsonlite помещает этот словарь в список (длина 1).

Если вы наркоман tidyverse (не значит, что так плохо):

library(dplyr)
dat %>%
  mutate(
    custom_data = purrr::map(segment, ~ tibble(segment = .x)),
    tags = purrr::map(name, ~ tibble(name = .x))
  ) %>%
  select(-segment, -name) %>%
  jsonlite::toJSON(., pretty = TRUE)

Если вы предпочитаете data.table, то

library(data.table)
as.data.table(dat)[
][, c("custom_data", "tags") :=
      .(lapply(dat$segment, function(a) data.frame(segment = a)),
        lapply(dat$name, function(a) data.frame(name = a)))
  ][, c("segment", "name") := NULL
    ][, jsonlite::toJSON(.SD, pretty = TRUE) ]

или если вам все еще нравится "конвейерный" поток magrittr,

library(magrittr)
as.data.table(dat) %>%
  .[, c("custom_data", "tags") :=
        .(lapply(dat$segment, function(a) data.frame(segment = a)),
          lapply(dat$name, function(a) data.frame(name = a))) ] %>%
  .[, c("segment", "name") := NULL ] %>%
  jsonlite::toJSON(., pretty = TRUE)
person r2evans    schedule 27.03.2020