如何在R中将姓名国籍API结果存入新列并提取Top3得分?
问题修正方案与代码示例
核心问题分析
- Top3得分错误:未按单个姓名分组计算,导致取的是全局Top3而非每个姓名的Top3。
bind_rows报错:API返回结果结构不统一(如空响应、无列名),或未将ID/name与API结果正确绑定,导致合并时出现无命名参数的问题。
修正后完整代码
library(dplyr) library(purrr) library(jsonlite) library(tibble) # 1. 定义name-prism API调用函数(含异常处理) get_nationality_scores <- function(name) { # 替换为真实的name-prism API端点 api_endpoint <- paste0("https://api.name-prism.com/api/version1/json/", URLencode(name)) # 调用API并捕获错误 response <- tryCatch( fromJSON(api_endpoint), error = function(e) NULL, warning = function(w) NULL ) # 处理空响应/异常,返回标准结构的空tibble if (is.null(response)) { return(tibble(nat = character(), score = numeric())) } # 将API返回的宽格式结果转为长格式,确保列名规范 response %>% as.data.frame() %>% rownames_to_column(var = "nat") %>% rename(score = 2) %>% mutate(score = as.numeric(score)) } # 2. 处理原始数据,生成目标长格式结果 # 假设原始df结构:df <- tibble(ID = 1:5, name = c("John Doe", "Li Ming", "Maria Garcia", "Ahmed Khan", "Anna Ivanova")) final_result <- df %>% # 为每个姓名调用API,绑定结果到新列 mutate(nat_results = map(name, get_nationality_scores)) %>% # 展开嵌套数据,保留ID和name关联 unnest(nat_results) %>% # 按ID+姓名分组,取每组内得分Top3 group_by(ID, name) %>% arrange(desc(score), .by_group = TRUE) %>% slice_head(n = 3) %>% ungroup() %>% # 调整列顺序(可选) select(ID, name, nat, score)
关键修正点说明
1. 解决Top3分组问题
通过group_by(ID, name)将数据按单个姓名分组,再在组内用arrange(desc(score))排序,最后slice_head(n=3)提取每组的Top3得分,确保每个姓名的结果独立计算。
2. 解决bind_rows报错问题
- 在API调用函数中,强制返回标准结构的tibble:即使API请求失败,也返回包含
nat和score列的空tibble,避免出现无列名的元素。 - 使用
unnest替代直接bind_rows:unnest会自动将嵌套的data frame与外层的ID/name列绑定,确保合并时结构一致。
额外注意事项
- API速率限制:name-prism存在请求频率限制,建议在
get_nationality_scores函数中添加Sys.sleep(1)来控制请求间隔,避免被封禁。 - 响应格式兼容:如果API返回非JSON格式(如XML),需调整解析逻辑(如使用
xml2包处理)。 - 空值处理:可根据需求添加对空得分结果的过滤逻辑(如
filter(!is.na(score)))。
内容的提问来源于stack exchange,提问作者user12157566
相关产品推荐
相关产品推荐

