Преобразование вложенного файла JSON в формат данных R - PullRequest
2 голосов
/ 25 марта 2020

Я пытаюсь преобразовать файл JSON с несколькими уровнями вложенности в фрейм данных в R. Я рассмотрел некоторые существующие вопросы / ответы по этой проблеме (например, Преобразовать JSON в R Фрейм данных и Свести вложенный JSON в фрейм данных в R и Вложенный JSON в фрейм данных в R ), но поскольку я впервые обрабатываю файл JSON Я действительно борюсь.

Файл JSON довольно большой и содержит данные Twitter. Вот пример, чтобы показать, как выглядит структура вложения:

[
{
    "Corpus": "ALM",
    "Tweets": [
        {
            "tweet_id": "521033092132503552",
            "tweet_text": "no tweet text available",
            "date": "no date available",
            "annotations": [
                {
                    "annotator": "annotator00",
                    "annotation": "care"
                },
                {
                    "annotator": "annotator01",
                    "annotation": "care,purity"
                },
                {
                    "annotator": "annotator02",
                    "annotation": "care,purity"
                },
                {
                    "annotator": "annotator03",
                    "annotation": "care"
                }
            ]
        },
        {
            "tweet_id": "537681598989475841",
            "tweet_text": "Wholeheartedly support these protests & acts of civil disobedience & will join when I can! #Ferguson #AllLivesMatter",
            "date": "Wed Nov 26 18:57:37 +0000 2014",
            "annotations": [
                {
                    "annotator": "annotator00",
                    "annotation": "subversion"
                },
                {
                    "annotator": "annotator01",
                    "annotation": "subversion"
                },
                {
                    "annotator": "annotator02",
                    "annotation": "loyalty"
                },
                {
                    "annotator": "annotator03",
                    "annotation": "loyalty,subversion"
                }
            ]
        },

Вот некоторые данные этого же файла данных, но разные наблюдения / твиты (обратите внимание, что из-за того, что файл настолько велик, самый большой уровень вложения сокращается выкл.):

list(tweet_id = "500745903054258177", tweet_text = "@MichaelSkolnik Thank you for joining the solidarity effort #DearMikesMom #AllLivesMatter", 
    date = "Sat Aug 16 20:48:21 +0000 2014", annotations = list(
        list(annotator = "annotator01", annotation = "loyalty"), 
        list(annotator = "annotator02", annotation = "loyalty"), 
        list(annotator = "annotator03", annotation = "loyalty"))), 
list(tweet_id = "621859689270120448", tweet_text = "no tweet text available", 
    date = "no date available", annotations = list(list(annotator = "annotator01", 
        annotation = "betrayal"), list(annotator = "annotator02", 
        annotation = "non-moral"), list(annotator = "annotator03", 
        annotation = "fairness"))), list(tweet_id = "551227029874438145", 

Мой желаемый вывод будет выглядеть следующим образом:

   corpus tweet_id               tweet_text              date    annotator           annotation  
1     ALM  5210...  no tweet text available  no date available          00                 care
2     ALM  5210...  no tweet text available  no date available          01         care, purity
3     ALM  5210...  no tweet text available  no date available          02         care, purity
4     ALM  5210...  no tweet text available  no date available          03                 care
5     ALM  5376...  Wholeheartedly suppo...  Wed Nov 26 18:...          00           subversion
6     ALM  5376...  Wholeheartedly suppo...  Wed Nov 26 18:...          01           subversion 
7     ALM  5376...  Wholeheartedly suppo...  Wed Nov 26 18:...          02              loyalty           
8     ALM  5376...  Wholeheartedly suppo...  Wed Nov 26 18:...          03  loyalty, subversion           
...      

Как мне преобразовать файл JSON в желаемый вывод данных из фрейма?


Я импортировал файл JSON и попытался сгладить его так:

myData <- fromJSON(file = "my_json_file.json")
myData_flat <- as.data.frame(myData)

Но этого явно недостаточно:

str(myData_flat)
'data.frame':   1 obs. of  352130 variables:
 $ Corpus                              : Factor w/ 1 level "ALM": 1
 $ Tweets.tweet_id                     : Factor w/ 1 level "521033092132503552": 1
 $ Tweets.tweet_text                   : Factor w/ 1 level "no tweet text available": 1
 $ Tweets.date                         : Factor w/ 1 level "no date available": 1
 $ Tweets.annotations.annotator        : Factor w/ 1 level "annotator00": 1
 $ Tweets.annotations.annotation       : Factor w/ 1 level "care": 1
 $ Tweets.annotations.annotator.1      : Factor w/ 1 level "annotator01": 1
 $ Tweets.annotations.annotation.1     : Factor w/ 1 level "care,purity": 1
 $ Tweets.annotations.annotator.2      : Factor w/ 1 level "annotator02": 1
 $ Tweets.annotations.annotation.2     : Factor w/ 1 level "care,purity": 1
 $ Tweets.annotations.annotator.3      : Factor w/ 1 level "annotator03": 1
 $ Tweets.annotations.annotation.3     : Factor w/ 1 level "care": 1
 $ Tweets.tweet_id.1                   : Factor w/ 1 level "537681598989475841": 1
 $ Tweets.tweet_text.1                 : Factor w/ 1 level "Wholeheartedly support these protests &amp; acts of civil disobedience &amp; will join when I can! #Ferguson #A"| __truncated__: 1
 $ Tweets.date.1                       : Factor w/ 1 level "Wed Nov 26 18:57:37 +0000 2014": 1
 $ Tweets.annotations.annotator.4      : Factor w/ 1 level "annotator00": 1
 $ Tweets.annotations.annotation.4     : Factor w/ 1 level "subversion": 1
 $ Tweets.annotations.annotator.5      : Factor w/ 1 level "annotator01": 1
 $ Tweets.annotations.annotation.5     : Factor w/ 1 level "subversion": 1
 $ Tweets.annotations.annotator.6      : Factor w/ 1 level "annotator02": 1
 $ Tweets.annotations.annotation.6     : Factor w/ 1 level "loyalty": 1
 $ Tweets.annotations.annotator.7      : Factor w/ 1 level "annotator03": 1
 $ Tweets.annotations.annotation.7     : Factor w/ 1 level "loyalty,subversion": 1
...

1 Ответ

2 голосов
/ 25 марта 2020

В R есть несколько пакетов для чтения в JSON данных и функции fromJSON(). RJSONOIO, jsonlite и rjson - это те, о которых я знаю. Кажется, вы используете rjson::fromJSON() в своем коде.

Поскольку формат json очень гибок в том, как он может хранить данные и способен хранить сложные, вложенные структуры, когда мы преобразуем его в относительно сложного формата data.frame мы должны быть очень недвусмысленными в отношении структуры данных. Ваш случай довольно прост, но он может быть очень утомительным, чтобы захватить весь диапазон представлений данных в файле json при преобразовании в прямоугольную angular форму data.frame.

rjson::fromJSON() генерирует вложенный список, который напоминает структуру файла JSON.

Структура вашего myData list выглядит примерно так:

myData[[1]]:
  - $Corpus
  - $Tweets
      - $[[1]]
          - tweet data
      - $[[2]]
          - tweet data

Для извлечения данных, которые вы ищете, вы хотите переключаться между записями mydata[[1]]$tweets подсписок, преобразовать их в data.frame и затем связать все эти data.frame s в один большой data.frame. Вы можете сделать это с for l oop или чем-то вроде lapply(). Я бы предложил использовать purrr::map_dfr(), так как он автоматически связывает результаты каждой вложенной операции в один data.frame.

Я обнаружил, что следующее должно работать для ваших данных. К счастью tibble::as.tibble() хорошо работает для ваших данных. Вы применяете его один раз к каждой записи твита, а после этого применяете его к каждому набору annotator, annotion, и вы получите результат, который вы ищете.

library(rjson)
myData <- fromJSON(file = "my_json_file.json")

library(purrr)
library(dplyr)

myData_df <- map_dfr(myData[[1]]$Tweets, as.tibble)

annotations_df <- map_dfr(myData_df$annotations, as.tibble)

myData_df %>% 
  select(-annotations) %>% 
  bind_cols(annotations_df)

># A tibble: 8 x 5
>  tweet_id      tweet_text                                               date              annotator annotation   
  <chr>         <chr>                                                    <chr>             <chr>     <chr>        
1 521033092132… no tweet text available                                  no date available annotato… care         
2 521033092132… no tweet text available                                  no date available annotato… care,purity  
3 521033092132… no tweet text available                                  no date available annotato… care,purity  
4 521033092132… no tweet text available                                  no date available annotato… care         
5 537681598989… Wholeheartedly support these protests &amp; acts of civ… Wed Nov 26 18:57… annotato… subversion   
6 537681598989… Wholeheartedly support these protests &amp; acts of civ… Wed Nov 26 18:57… annotato… subversion   
7 537681598989… Wholeheartedly support these protests &amp; acts of civ… Wed Nov 26 18:57… annotato… loyalty      
8 537681598989… Wholeheartedly support these protests &amp; acts of civ… Wed Nov 26 18:57… annotato… loyalty,subv…
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...