API调用dplyr管道中列类型变化时tidyr::hoist的错误处理
解决方案
1. 自定义安全提取函数适配hoist
针对列类型不稳定的问题,写个兼容全NA和非嵌套列表的安全函数,直接在dplyr管道里用:
safe_hoist <- function(data, col, ...) { # 先判断列是否全为NA if (all(is.na(data[[col]]))) { new_cols <- names(list(...)) data[new_cols] <- NA return(data) } # 判断是否存在嵌套列表元素 has_nested <- any(purrr::map_lgl(data[[col]], ~!is.na(.) && is.list(.))) if (!has_nested) { new_cols <- names(list(...)) data[new_cols] <- NA return(data) } # 正常执行hoist tidyr::hoist(data, {{col}}, ...) }
管道使用示例:
library(dplyr) library(tidyr) library(purrr) # 假设nested_col是不稳定的目标列 processed_data <- raw_api_data %>% safe_hoist(nested_col, issue_type = "name", assignee = list("assignee", "displayName")) %>% select(-nested_col) # 按需移除原嵌套列
2. 在API循环阶段统一数据结构
从源头避免结构不一致,在while循环拉取每一页数据时,先强制把不稳定列转为列表类型:
all_pages <- list() start <- 0 page_size <- 25 while(TRUE) { # 调用Jira API(替换成你的实际调用代码) api_res <- get_jira_dashboard(start_at = start, max_results = page_size) page_data <- api_res$content # 强制将目标列转为列表,不管是NA还是单个值 page_data <- page_data %>% mutate(across(c(nested_col1, nested_col2), ~purrr::map(., function(x) { if (is.na(x)) return(list()) if (!is.list(x)) return(list(value = x)) x }))) all_pages <- c(all_pages, list(page_data)) # 终止循环条件 if (start + page_size >= api_res$total) break start <- start + page_size } # 合并后正常用hoist提取 final_data <- bind_rows(all_pages) %>% hoist(nested_col1, type = "name") %>% hoist(nested_col2, assignee = "displayName")
3. 单字段的灵活提取方案
如果只需要处理个别字段,直接用map+tryCatch在mutate里处理,不用hoist:
processed_data <- raw_api_data %>% mutate( assignee = purrr::map_chr(nested_col, function(x) { # 非列表/NA直接返回NA if (is.na(x) || !is.list(x)) return(NA_character_) # 提取失败也返回NA tryCatch(x$assignee$displayName, error = function(e) NA_character_) }) )
内容的提问来源于stack exchange,提问作者PhDavey
相关产品推荐
相关产品推荐

