【问题标题】:How to use an API in R to be able to get data for storing into a db?如何在 R 中使用 API 来获取数据以存储到数据库中?
【发布时间】:2021-01-15 16:30:37
【问题描述】:

我试图弄清楚如何在 R 中获取数据,以便将其制作成可以存储到 sql 等数据库中的表。

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

然后我尝试解析这些数据并将其转换为数据框,但是当我这样做时,我得到了以下错误: “错误:必须命名第 4、5、6、7、8 和 178 列。 使用 .name_repair 指定修复。”和“错误:Tibble 列必须具有兼容的大小。 * 大小 2:列 deathscasesConfirmedstringency。 * 大小 176:列 ..2020.12.27..2020.12.28..2020.12.29 和"

我不确定是否有更好的方法或如何解析它。有什么方法或方法吗?我在网上运气不好。

【问题讨论】:

  • 至少有一个问题:{} 未包含在 API 调用中(假设它们在文档中表示“替换”)。建议直接在浏览器中调用API熟悉结果。
  • @DinoCoderSaurus 是的,我知道 {} 不包括在内,只是将此作为日期的示例,问题不在这里,而是稍后
  • 顺便说一句,对于以后的问题,当您收到错误消息并向我们提供错误消息时,了解您用于导致该错误的代码确实很有帮助。例如,我不清楚您是否使用read.tableread.csvreadr::* 等。虽然所有这些仍然是此类数据的错误答案(请参阅我的答案),但关键是我们不知道你尝试了什么,所以帮助你修复你的代码是不可能的。

标签: r database sqlite data-science data-analysis


【解决方案1】:

您似乎正在尝试从该 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$datajs$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。不幸的是,我不知道有一个简单的工具可以递归地遍历列表(即使rapply 在我的测试中也不能很好地工作),所以我们在这里使用三重-@987654338 会有点蛮力@:

长话短说,

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多