#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 )