R语言循环调用API时如何保留每次迭代变量并填充缺失值为NA
R语言API循环调用缺失字段自动填充NA实现方案
需求说明
现有代码可迭代调用两次GitHub JSON格式API,循环内会将接口返回结果转换为数据框,需要实现:迭代过程中保留所有返回字段,若单次迭代中某字段不存在,自动填充NA值,避免多批次结果合并时出现列不匹配报错。
原示例代码
library(jsonlite) library(httpuv) library(httr) myapp <- oauth_app(appname = "insert_your_credentials", key = "insert_your_credentials", secret = "insert_your_credentials") github_token <- oauth2.0_token(oauth_endpoints("github"), myapp) gtoken <- config(token = github_token) df <- data.frame(link = c("https://api.github.com/search/commits?q=%22image%22+AND+%22covid%22?page=1&per_page=100", "https://api.github.com/search/commits?q=%22image%22+AND+%22covid%22?page=2&per_page=100")) for (i in 1:nrow(df)) { req <- GET(df$link[i]) # Extract content from a request json1 = content(req) # Convert to a data.frame char <- rawToChar(req$content) dfcollection <- jsonlite::fromJSON(char) }
实现方案
核心逻辑是在循环内逐次对齐所有批次返回的字段名,对缺失字段统一赋值NA后再做行绑定,具体修改点如下:
- 循环外提前初始化空的总结果存储对象
- 每次请求解析完当前批次数据后,先和历史总结果比对,取所有字段的并集作为标准列结构
- 分别给当前批次、历史总结果补全自身缺失的列,统一填充NA
- 列结构完全对齐后再追加合并到总结果
- 补充原代码遗漏的鉴权参数传入,避免API请求无权限
- 增加空结果判断,避免单页无返回时循环中断
修改后完整代码
library(jsonlite) library(httpuv) library(httr) myapp <- oauth_app(appname = "insert_your_credentials", key = "insert_your_credentials", secret = "insert_your_credentials") github_token <- oauth2.0_token(oauth_endpoints("github"), myapp) gtoken <- config(token = github_token) df <- data.frame(link = c("https://api.github.com/search/commits?q=%22image%22+AND+%22covid%22?page=1&per_page=100", "https://api.github.com/search/commits?q=%22image%22+AND+%22covid%22?page=2&per_page=100")) # 初始化空对象存储所有迭代的总结果 total_results <- NULL for (i in 1:nrow(df)) { # 补上原代码遗漏的鉴权参数 req <- GET(df$link[i], gtoken) # 解析JSON,flatten=TRUE可自动展平一级嵌套字段 char <- rawToChar(req$content) current_resp <- jsonlite::fromJSON(char, flatten = TRUE) # GitHub搜索接口的明细数据存放在items节点 current_df <- current_resp$items # 当前页无返回数据直接跳过 if (is.null(current_df) || nrow(current_df) == 0) { next } # 第一次迭代直接赋值 if (is.null(total_results)) { total_results <- current_df } else { # 获取所有批次出现过的全量字段 all_columns <- union(names(total_results), names(current_df)) # 给当前批次补全缺失字段,填充NA missing_in_current <- setdiff(all_columns, names(current_df)) current_df[missing_in_current] <- NA # 给历史总结果补全新出现的字段,填充NA missing_in_total <- setdiff(all_columns, names(total_results)) total_results[missing_in_total] <- NA # 按统一列顺序追加合并 total_results <- rbind(total_results, current_df[, all_columns]) } }
补充说明
- 如果需要处理接口请求异常的场景,可以在
GET请求外层包裹tryCatch,避免单次请求失败导致整个循环中断 - 若返回的JSON嵌套层级较深,
jsonlite::fromJSON会默认将嵌套结构解析为列表列,若需要展平可保留flatten = TRUE参数,会自动把嵌套的一级对象拆分为独立列
内容的提问来源于stack exchange,提问作者Domin D
相关产品推荐
相关产品推荐

