如何在R中合并数量不限的列表?UN API数据处理优化
批量合并联合国API返回数据的解决方案
问题场景
我通过循环从联合国人口API拉取多个国家的数据,但合并所有返回结果中的data列表时,目前只能手动用rbind()逐个指定元素,没法适配任意数量的国家数据,之前尝试在循环内用rbind()也没成功。现有代码如下:
library(jsonlite) library(httr) base_url <- "https://population.un.org/dataportalapi/api/v1/data" locationlist <- list("528","40","620") # example list of country codes target <- list() response <- list() for (i in locationlist) { target[[i]] <- paste0(base_url, "/indicators/",65,"/locations/",i,"/start/",2000,"/end/",2019) # url response[[i]] <- fromJSON(target[[i]]) # call API } # Here's the main issue : df <- rbind(response[[1]]$data,response[[2]]$data,response[[3]]$data) # combine lists
解决方案
方法1:Base R原生实现(无需额外包)
先把所有response里的data提取到一个列表,再用do.call()批量调用rbind合并,自动适配任意数量的元素:
# 提取所有response中的data部分到列表 data_list <- lapply(response, function(res) res$data) # 批量合并成数据框 df <- do.call(rbind, data_list)
方法2:用purrr包简化操作(更简洁)
如果习惯tidyverse风格,purrr的map_dfr可以一步完成提取+合并,自动按行绑定:
# 先安装并加载purrr(如果没装过) install.packages("purrr") library(purrr) # 直接提取所有response的data并合并 df <- map_dfr(response, ~ .x$data)
改进循环写法(节省内存)
可以直接在循环中只存储需要的data部分,避免额外保存target和完整response列表,之后再合并:
library(jsonlite) base_url <- "https://population.un.org/dataportalapi/api/v1/data" locationlist <- list("528","40","620") data_list <- list() for (i in locationlist) { url <- paste0(base_url, "/indicators/",65,"/locations/",i,"/start/",2000,"/end/",2019) # 直接存储data部分 data_list[[i]] <- fromJSON(url)$data } # 合并数据 df <- do.call(rbind, data_list)
循环内直接合并的正确姿势
你之前在循环内用rbind失败,大概率是因为没正确初始化数据框。如果一定要在循环内逐步合并,可以这么写(但数据量大时效率不如先存列表再合并):
df <- NULL for (i in locationlist) { url <- paste0(base_url, "/indicators/",65,"/locations/",i,"/start/",2000,"/end/",2019) new_data <- fromJSON(url)$data # 第一次循环初始化df,之后逐步合并 df <- if (is.null(df)) new_data else rbind(df, new_data) }
内容的提问来源于stack exchange,提问作者TomasPereira
相关产品推荐
相关产品推荐

