Нужна помощь в навигации по спискам при преобразовании JSON в dataframe/CSV

#r #json #dataframe #csv #web-scraping

#r #json #dataframe #csv #очистка веб-страниц

Вопрос:

Я пытаюсь очистить таблицу, отображаемую на javascript, и, попробовав как selenium, так и PhantomJS, я решил, что JSON будет самым простым способом сделать это. Однако я совсем новичок в R и не очень хорошо разбираюсь в обработке списков, и из-за этого я не могу перевести свои данные в желаемый формат таблицы. Я просмотрел несколько решений, но по какой-то причине они на самом деле не работают с тем JSON, который у меня есть.

Данные JSON отображаются через этот URL. И это фактический веб-сайт, на котором находится таблица.

Что я сделал до сих пор, так это попытался разобрать JSON в R и принудительно преобразовать его в dataframe, основываясь на том, что я видел из большинства ответов на stackoverflow.

 library(httr)
library(jsonlite)
rf <- GET(url) #the entire URL is very long so I'm not putting it here
rfc <- content(rf)
  

Выполнение этого возвращает мне большой список из четырех элементов, rfc. Затем я применяю следующую функцию.

 library(httr)
library(jsonlite)     
json_file <- lapply(rfc, function(x) {
      x[sapply(x, is.null)] <- NA
      unlist(x)
    })
  

Это возвращает мне сообщение об ошибке:

 Error in x[sapply(x, is.null)] <- NA : invalid subscript type 'list'
  

Учитывая, что мне нужен только второй элемент списка, в котором находится информация, я пытаюсь его подмножество:

   json_file <- lapply(rfc[2], function(x) {
  x[sapply(x, is.null)] <- NA
  unlist(x)
})
  

Это возвращает мне большой список размером 12 Мб. Когда я пытаюсь принудительно преобразовать его в фрейм данных, используя as.data.frame , R возвращает мне 506472 наблюдения за 1 переменной. Все разные столбцы были сведены в один, а заголовки исчезли.

Кто-нибудь может сказать мне, как я должен это делать? Здесьесть бесплатный онлайн-конвертер JSON в CSV, который прекрасно делает именно то, что мне нужно. Это то, что она производит:

введите описание изображения здесь

К сожалению, это не решение. Поскольку я намерен запустить это в Shiny, я хочу делать все в R. Любая помощь приветствуется, спасибо.

Ответ №1:

Вам нужно взять элемент rfc$data$DailyProductionAndFlowList , который сам по себе фактически является списком однорядных фреймов данных, и связать их вместе. Сначала вам нужно перезаписать NULL значения:

 df <- do.call(rbind, lapply(rfc$data$DailyProductionAndFlowList, function(x) {
  x[sapply(x, is.null)] <- "NULL"
  as.data.frame(x, stringsAsFactors = FALSE)
}))
  

Чтобы показать вам, что результат является разумным, я поместил его в tibble здесь для более удобной печати:

 as_tibble(df)
#> # A tibble: 3,997 x 11
#>    GasDate FacilityId FacilityName LocationId LocationName Demand Supply
#>    <chr>        <int> <chr>             <int> <chr>         <dbl>  <dbl>
#>  1 2020-0~     520047 Eastern Gas~     520008 Sydney        94.4     0  
#>  2 2020-0~     520047 Eastern Gas~     520009 Canberra      16.5     0  
#>  3 2020-0~     520047 Eastern Gas~     530015 Longford Hub   0     234. 
#>  4 2020-0~     520047 Eastern Gas~     590011 Regional - ~  22.4     0  
#>  5 2020-0~     520047 Eastern Gas~     590012 Regional - ~   2.68   19.4
#>  6 2020-0~     520047 Eastern Gas~     520008 Sydney       113.      0  
#>  7 2020-0~     520047 Eastern Gas~     520009 Canberra      19.7     0  
#>  8 2020-0~     520047 Eastern Gas~     530015 Longford Hub   0     225. 
#>  9 2020-0~     520047 Eastern Gas~     590011 Regional - ~  27.5     0  
#> 10 2020-0~     520047 Eastern Gas~     590012 Regional - ~   5.05   20.1
#> # ... with 3,987 more rows, and 4 more variables: TransferIn <dbl>,
#> #   TransferOut <dbl>, HeldInStorage <chr>, LastUpdated <chr>

  

Ответ №2:

Другой подход:

 library( data.table )
library( rjson )

#location of  data
json.url = "https://aemo.com.au/aemo/api/v1/GasBBReporting/DailyProductionAndFlow?FacilityIds=540093,580010,540101,544261,540047,530030,540083,540096,580020,540071,540077,520075,540059,520054,520090,540094,540098,540080,540090,540086,540050,540097,540055,520047,540089,540070,540092,530071,530042,540088,540075,544253,540061,530038,530039,530040,580100,580040,540064,530043,550050,550045,550046,550054,520053,530061,520060,580050,540084,530041,530044,580060,580070,540065,550052,530060,540058,540085,540102,540073,540057,540095,544260,540110,540040,540082,540072,540062,540103,550061,550060,540060,540066,540067,540076,540068,580210,570050,540051,532005,530110,540045,540046,540091,580030,540069,540087,580180,540074amp;FromGasDate=07/08/2020amp;ToGasDate=07/09/2020"
#retrieve lastest data
mydata <- data.table::rbindlist( rjson::fromJSON( file = json.url )$data$DailyProductionAndFlowList, 
                                 use.names = TRUE, fill = TRUE )