簡體   English   中英

如何在 R 中使用 API 來獲取數據以存儲到數據庫中?

[英]How to use an API in R to be able to get data for storing into a db?

我試圖弄清楚如何在 R 中獲取數據,以便將其制作成可以存儲到 sql 等數據庫中的表。

API <- "https://covidtrackerapi.bsg.ox.ac.uk/api/v2/stringency/date-range/{2020-01-01}/{2020-06-30}"
oxford_covid <- GET(API)

然后我嘗試解析這些數據並將其轉換為 dataframe 但是當我這樣做時出現以下錯誤:“錯誤:第 4、5、6、7、8 和 178 列必須命名。使用.name_repair 來指定修理。” 和“錯誤:Tibble 列必須具有兼容的大小。* 大小 2:列deathscasesConfirmedstringency 。* 大小 176:列..2020.12.27..2020.12.28..2020.12.29和”

我不確定是否有更好的方法或如何解析它。 有沒有方法或方法? 我在網上運氣不太好。

看起來您正在嘗試從 API 返回 JSON 並調用read.table或其他東西。 不要那樣做,JSON 應該由 JSON 工具(例如jsonlite::parse_json )解析。

URL 的一些工作。

js <- jsonlite::parse_json(url("https://covidtrackerapi.bsg.ox.ac.uk/api/v2/stringency/date-range/2020-01-01/2020-06-30"))
lengths(js)
#     scale countries      data 
#         3       183       182 

str(js, max.level = 2, list.len = 3)
# List of 3
#  $ scale    :List of 3
#   ..$ deaths        :List of 2
#   ..$ casesConfirmed:List of 2
#   ..$ stringency    :List of 2
#  $ countries:List of 183
#   ..$ : chr "ABW"
#   ..$ : chr "AFG"
#   ..$ : chr "AGO"
#   .. [list output truncated]
#  $ data     :List of 182
#   ..$ 2020-01-01:List of 183
#   ..$ 2020-01-02:List of 183
#   ..$ 2020-01-03:List of 183
#   .. [list output truncated]

所以這個比較大。 由於您希望使用data.frame ,因此我將僅查看js$data js$countries看起來比較無趣,

str(unlist(js$countries))
#  chr [1:183] "ABW" "AFG" "AGO" "ALB" "AND" "ARE" "ARG" "AUS" "AUT" "AZE" "BDI" "BEL" "BEN" "BFA" "BGD" "BGR" "BHR" "BHS" "BIH" "BLR" "BLZ" "BMU" "BOL" "BRA" "BRB" "BRN" "BTN" "BWA" "CAF" "CAN" "CHE" "CHL" "CHN" "CIV" "CMR" "COD" "COG" "COL" "CPV" ...

並且與js$data無關。 js$scale可能很有趣,但我現在將跳過它。

我第一次將這樣的數據加入data.frame是以下之一,具體取決於您對 R 方言的偏好:

do.call(rbind.data.frame, list_of_frames)  # base R
dplyr::bind_rows(list_of_frames)           # tidyverse
data.table::rbindlist(list_of_frames)      # data.table

但是我們會遇到問題。 也就是說,有些條目是NULL ,而 R 更喜歡它們是某物(例如NA )。

str(js$data[[1]][1])
# List of 2
#  $ ABW:List of 8
#   ..$ date_value            : chr "2020-01-01"
#   ..$ country_code          : chr "ABW"
#   ..$ confirmed             : NULL                # <--- problem
#   ..$ deaths                : NULL
#   ..$ stringency_actual     : int 0
#   ..$ stringency            : int 0
#   ..$ stringency_legacy     : int 0
#   ..$ stringency_legacy_disp: int 0

因此,我們需要遍歷其中的每一個並將NULL替換為NA 不幸的是,我不知道有一個簡單的工具可以通過列表列表遞歸 go(甚至rapply在我的測試中也不能很好地工作),所以我們在這里使用三重lapply有點蠻力:

長話短說,

str(js$data[[1]][[1]])
# List of 8
#  $ date_value            : chr "2020-01-01"
#  $ country_code          : chr "ABW"
#  $ confirmed             : NULL
#  $ deaths                : NULL
#  $ stringency_actual     : int 0
#  $ stringency            : int 0
#  $ stringency_legacy     : int 0
#  $ stringency_legacy_disp: int 0
jsdata <-
  lapply(js$data, function(z) {
    lapply(z, function(y) {
      lapply(y, function(x) if (is.null(x)) NA else x)
    })
  })
str(jsdata[[1]][[1]])
# List of 8
#  $ date_value            : chr "2020-01-01"
#  $ country_code          : chr "ABW"
#  $ confirmed             : logi NA
#  $ deaths                : logi NA
#  $ stringency_actual     : int 0
#  $ stringency            : int 0
#  $ stringency_legacy     : int 0
#  $ stringency_legacy_disp: int 0

(從技術上講,如果我們知道它將是整數,我們應該使用NA_integer_ 。幸運的是,R 及其方言能夠使用這個快捷方式,我們稍后會看到。)

之后,我們可以進行雙重綁定並回到我之前討論的框架制作步驟。 選擇以下選項之一,無論您喜歡哪種方言:

alldat <- do.call(rbind.data.frame,
                  lapply(jsdata, function(z) do.call(rbind.data.frame, z)))
alldat <- dplyr::bind_rows(purrr::map(jsdata, dplyr::bind_rows))
alldat <- data.table::rbindlist(lapply(jsdata, data.table::rbindlist))

為簡單起見,我將展示第一個(基本 R)版本:

tail(alldat)
#                date_value country_code confirmed deaths stringency_actual stringency stringency_legacy stringency_legacy_disp
# 2020-06-30.AND 2020-06-30          AND       855     52             42.59      42.59             65.47                  65.47
# 2020-06-30.ARE 2020-06-30          ARE     48667    315             72.22      72.22             83.33                  83.33
# 2020-06-30.AGO 2020-06-30          AGO       284     13             75.93      75.93             83.33                  83.33
# 2020-06-30.ALB 2020-06-30          ALB      2535     62             68.52      68.52             78.57                  78.57
# 2020-06-30.ABW 2020-06-30          ABW       103      3             47.22      47.22             63.09                  63.09
# 2020-06-30.AFG 2020-06-30          AFG     31507    752             78.70      78.70             76.19                  76.19

如果你對$scale感到好奇,

do.call(rbind.data.frame, js$scale)
#                min     max
# deaths           0  127893
# casesConfirmed   0 2633466
# stringency       0     100

## or

data.table::rbindlist(js$scale, idcol="id")
#                id   min     max
#            <char> <int>   <int>
# 1:         deaths     0  127893
# 2: casesConfirmed     0 2633466
# 3:     stringency     0     100

## or

dplyr::bind_rows(js$scale, .id = "id")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM