繁体   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