如何高效查找多个R向量中的重复元素集合?
解决方案:用分组聚合高效找出跨国家重复出现的姓名
可以利用tidyverse工具链(或base R)通过分组-聚合的方式高效实现需求,避免手动构建二进制矩阵的繁琐和潜在性能问题。以下是具体步骤:
步骤1:整理数据为长格式
首先将分散的国家向量整合为一个统一的长格式数据框,便于后续处理:
# 定义原始数据 France <- c("John", "Michael" , "Bob", "Oliver") Italy <- c("Hugo", "Oliver", "Soren", "Jackson", "John") Spain <- c("Joseph", "David", "Bob", "John", "Leo", "Michael") Austria <- c("Oliver", "Giovanni", "Luka") # 把所有国家向量存入列表,再转换为长格式数据框 library(tidyverse) country_list <- list(France = France, Italy = Italy, Spain = Spain, Austria = Austria) name_country_df <- country_list %>% enframe(name = "Country", value = "Name") %>% unnest(Name)
步骤2:按姓名聚合所属国家
为每个姓名收集其去过的所有国家,形成国家集合:
name_countries <- name_country_df %>% group_by(Name) %>% summarise(Countries = list(sort(Country))) %>% # 排序保证国家顺序一致,避免重复分组 ungroup()
步骤3:按国家集合反向聚合姓名
将去过相同国家组合的姓名归为一组,同时筛选出包含2个及以上国家的组合:
country_groups <- name_countries %>% group_by(Countries) %>% summarise(Names = list(Name)) %>% ungroup() %>% filter(lengths(Countries) >= 2) # 只保留至少去过2个国家的姓名组
步骤4:生成符合要求的中文句子
自定义一个函数处理中文格式的字符串连接(2个元素用"和",多个元素用"、"分隔最后一个用"和"),然后生成最终结果:
# 中文格式连接函数 join_chinese <- function(x) { if (length(x) == 1) { x } else if (length(x) == 2) { str_c(x, collapse = "和") } else { str_c(c(str_c(x[-length(x)], collapse = "、"), x[length(x)]), collapse = "和") } } # 生成结果句子 result <- country_groups %>% mutate( Name_str = map_chr(Names, join_chinese), Country_str = map_chr(Countries, join_chinese), Sentence = str_c(Name_str, "去过", Country_str) ) %>% pull(Sentence) # 输出结果 print(result)
运行后得到的结果完全符合需求:
[1] "John和Oliver去过France和Italy" "John、Michael和Bob去过France和Spain" "Oliver去过France、Italy和Austria"
为什么这个方法高效?
- 避免了手动构建二进制矩阵和遍历的低效操作,全程使用向量化的分组聚合逻辑,处理大数据量时性能优势明显;
tidyverse的链式操作代码简洁易读,便于维护和扩展(比如新增国家向量只需添加到country_list即可)。
Base R替代方案
如果不想依赖tidyverse,也可以用base R实现相同逻辑:
# 构建长格式数据 country_list <- list(France = France, Italy = Italy, Spain = Spain, Austria = Austria) name_country_df <- data.frame( Name = unlist(country_list), Country = rep(names(country_list), sapply(country_list, length)) ) # 按姓名聚合国家 name_countries <- aggregate(Country ~ Name, data = name_country_df, FUN = function(x) sort(x)) name_countries$Country_key <- sapply(name_countries$Country, paste, collapse = ",") # 按国家集合聚合姓名 country_groups <- aggregate(Name ~ Country_key, data = name_countries, FUN = list) country_groups$Countries <- strsplit(country_groups$Country_key, ",") country_groups <- country_groups[sapply(country_groups$Countries, length) >= 2, ] # 中文连接函数 join_chinese <- function(x) { if (length(x) == 1) x else if (length(x) == 2) paste(x, collapse = "和") else paste(c(paste(x[-length(x)], collapse = "、"), x[length(x)]), collapse = "和") } # 生成结果 result <- mapply(function(names, countries) paste(join_chinese(names), "去过", join_chinese(countries)), country_groups$Name, country_groups$Countries) print(result)
内容的提问来源于stack exchange,提问作者atawfik14
相关产品推荐
相关产品推荐

