#json #r #dataframe #sapply #do.call
#json #r #фрейм данных #sapply #do.call
Вопрос:
Я пытаюсь правильно преобразовать JSON в data.frame с 3 столбцами.
Это упрощение моих данных
# simplification of my real data
my_data <- '{"Bag 1": [["bananas", 1], ["oranges", 2]],"Bag 2": [["bananas", 3], ["oranges", 4], ["apples", 5]]}'
library(jsonlite)
my_data <- fromJSON(my_data)
> my_data
$`Bag 1`
[,1] [,2]
[1,] "bananas" "1"
[2,] "oranges" "2"
$`Bag 2`
[,1] [,2]
[1,] "bananas" "3"
[2,] "oranges" "4"
[3,] "apples" "5"
Я пытаюсь преобразовать это в data.frame
# this return an error about "arguments imply differing number of rows: 2, 3"
my_data <- as.data.frame(my_data)
> my_data <- as.data.frame(my_data)
Error in (function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE, :
arguments imply differing number of rows: 2, 3
Это мое решение для создания data.frame
# my solution
my_data <- data.frame(fruit = do.call(c, my_data),
bag_number = rep(1:length(my_data),
sapply(my_data, length)))
# how it looks
my_data
> my_data
fruit bag_number
Bag 11 bananas 1
Bag 12 oranges 1
Bag 13 1 1
Bag 14 2 1
Bag 21 bananas 2
Bag 22 oranges 2
Bag 23 apples 2
Bag 24 3 2
Bag 25 4 2
Bag 26 5 2
Но моя идея состоит в том, чтобы получить что-то подобное, чтобы избежать проблем, подобных my_data[a:b,1]
тому, когда я хочу использовать ggplot2 и другие.
fruit | quantity | bag_number
oranges | 2 | 1
bananas | 1 | 1
oranges | 4 | 2
bananas | 3 | 2
apples | 5 | 2
Комментарии:
1. Ваш примерный набор данных не выдает первоначальный вывод. Вместо этого он создает вложенный список списков, с которым очень сложно работать. Я использую
rjson::fromJSON
.2. спасибо, да, я изменил его сейчас
Ответ №1:
library(plyr)
# import data (note that the rJSON package does this differently than the jsonlite package)
data.import <- jsonlite::fromJSON(my_data)
# combine all data using plyr
df <- ldply(data.import, rbind)
# clean up column names
colnames(df) <- c('bag_number', 'fruit', 'quantity')
bag_number fruit quantity
1 Bag 1 bananas 1
2 Bag 1 oranges 2
3 Bag 2 bananas 3
4 Bag 2 oranges 4
5 Bag 2 apples 5
Комментарии:
1. Я понимаю, что jsonlite и rJSON делают то же самое, но на самом деле разные. Большое спасибо.
Ответ №2:
purrr
/ tidyverse версия. Вы также получаете правильные типы с этим и избавляетесь от « Bag
«:
library(jsonlite)
library(purrr)
library(readr)
fromJSON(my_data, flatten=TRUE) %>%
map_df(~as.data.frame(., stringsAsFactors=FALSE), .id="bag") %>%
type_convert() %>%
setNames(c("bag_number", "fruit", "quantity")) -> df
df$bag_number <- gsub("Bag ", "", df$bag_number)
Комментарии:
1. Большое спасибо.
purrr
также полезно.