【问题标题】:Faster download for paginated nested JSON data from API in R?从 R 中的 API 更快地下载分页嵌套 JSON 数据?
【发布时间】:2019-08-06 12:13:42
【问题描述】:

我正在从联合国的 SDG 指标 API 下载嵌套的 json 数据,但是使用 50,006 个分页的循环太慢了,无法完成。有没有更好的办法?

https://unstats.un.org/SDGAPI/swagger/#!/Indicator/V1SdgIndicatorDataGet

我正在使用 Windows 笔记本电脑上的 RStudio 工作。获取 json 嵌套数据并将其结构化为数据框是一场艰苦的胜利,但处理分页让我很难过。联合国统计电子邮件没有回复。 也许“申请”会做到这一点?我只需要 2004 年、2007 年和 2011 年的数据——也许我可以过滤,但我认为这对根本问题没有帮助。

我可能误解了 API 结构 - 我看不出单独查询 50,006 个页面如何对任何人都有效。感谢您的任何见解!

library(dplyr)
library(httr)
library(jsonlite)

#Get data from the first page, and initialize dataframe and data types
  page1 <- fromJSON("https://unstats.un.org/SDGAPI/v1/sdg/Indicator/Data", flatten = TRUE)
  #Get number of pages from the field of the first page
  pages <- page1$totalPages
  SDGdata<- data.frame()
  for(j in 1:25){
    SDGdatarow <- rbind(page1$data[j,1:16])
    SDGdata <- rbind(SDGdata,SDGdatarow)
  }
  SDGdata[1] <- as.character(SDGdata[[1]])
  SDGdata[2] <- as.character(SDGdata[[2]])
  SDGdata[3] <- as.character(SDGdata[[3]])

#Loop through all the rest of the pages
baseurl <- ("https://unstats.un.org/SDGAPI/v1/sdg/Indicator/Data")
  for(i in 2:pages){
    mydata <- fromJSON(paste0(baseurl, "?page=", i), flatten=TRUE)
    message("Retrieving page ", i)
    for(j in 1:25){
      SDGdatarow <- rbind(mydata$data[j,1:16])
      rownames(SDGdatarow) <- as.numeric((i-1)*25+j)
      SDGdata <- rbind.data.frame(SDGdata,SDGdatarow)
    }
}

我确实得到了我想要的数据,并且在一个不错的数据框中,但是在几百页之后,查询不可避免地会出现连接问题,或者我的笔记本电脑关闭等。每页大约需要 5 秒。 5*50,006/3600 ~= 70 小时。

【问题讨论】:

  • 一些事情。用*apply 或其他东西替换循环。不知道为什么要这样做两次? SDGdatarow &lt;- rbind(mydata$data[j,1:16])。为什么不对所有页面执行一次?
  • 谢谢。首先获取第一页有助于设置我认为的数据框和类型,有助于索引,并且不需要任何实时。我曾尝试使用“应用”,但我并不擅长,并且不知道如何让它发挥作用(目前)。
  • API 文档中一定遗漏了一些东西。这似乎(在我看来)在计算上不值得。
  • 我想我想通了:我可以设置每页的元素数量,从而可以控制可管理的页面数量。我还过滤了我想要的 3 年,这减少了数据。通过实验,我发现大约 1/10 的元素可以下载,所以我将调用设置为每页 1/10,循环 10 页。大约需要 20 分钟,但比 70 小时要好,并且可以在不丢失连接的情况下工作。

标签: r json api download


【解决方案1】:

我想我(终于)找到了一个可行的解决方案:我可以设置每页的元素数量,从而使要调用的页面数量可控。 (我还过滤了我想要的 3 年,这减少了数据)。通过实验,我发现大约 1/10 的元素可以下载,所以我将调用设置为每页 1/10,循环 10 页。大约需要 20 分钟,但比 70 小时要好,并且可以在不丢失连接的情况下工作。

  #initiate the df
  SDGdata<- data.frame()
  # call to get the # elements with the years filter
  page1 <- fromJSON("https://unstats.un.org/SDGAPI/v1/sdg/Indicator/Data?timePeriod=2004&timePeriod=2007&timePeriod=2011", flatten = TRUE)
  perpage <- ceiling(page1$totalElements/10)
  ptm <- proc.time()
  for(i in 1:10){
    SDGpage <- fromJSON(paste0("https://unstats.un.org/SDGAPI/v1/sdg/Indicator/Data?timePeriod=2004&timePeriod=2007&timePeriod=2011&pageSize=",perpage,"&page=",i), flatten = TRUE)
    message("Retrieving page ", i, " :", (proc.time() - ptm) [3], " seconds")
    SDGdata <- rbind(SDGdata,SDGpage$data[,1:16])
      }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-07
    • 2015-10-02
    • 1970-01-01
    相关资源
    最近更新 更多