在R语言中根据元素的列表归属为数据框添加新列
为DataFrame添加分组归属标注列的R实现
现有数据
我有如下结构的DataFrame:
GroupsA GroupsB G1 G2 G1 G3 G1 G4 G1 G5 G1 G6 G2 G3 G2 G4 G2 G5 G2 G6 G3 G4 G3 G5 G3 G6 G4 G5 G4 G6 G5 G6
对应的dput格式:
structure(list(GroupsA = c("G1", "G1", "G1", "G1", "G1", "G2", "G2", "G2", "G2", "G3", "G3", "G3", "G4", "G4", "G5"), GroupsB = c("G2", "G3", "G4", "G5", "G6", "G3", "G4", "G5", "G6", "G4", "G5", "G6", "G5", "G6", "G6")), class = "data.frame", row.names = c(NA, -15L ))
同时定义了3个分组列表:
list1 <- c("G1","G3") list2 <- c("G2") list3 <- c("G4","G5","G6")
期望效果
希望新增一列Lists,标注每行中GroupsA和GroupsB所属的列表名称,格式为「列表名&列表名」,最终结果如下:
GroupsA GroupsB Lists G1 G2 list1&list2 G1 G3 list1&list1 G1 G4 list1&list3 G1 G5 list1&list3 G1 G6 list1&list3 G2 G3 list2&list1 G2 G4 list2&list3 G2 G5 list2&list3 G2 G6 list2&list3 G3 G4 list1&list3 G3 G5 list1&list3 G3 G6 list1&list3 G4 G5 list3&list3 G4 G6 list3&list3 G5 G6 list3&list3
解决方案
方法1:使用dplyr包实现
通过case_when匹配每个分组所属的列表,再拼接成目标格式:
library(dplyr) # 加载数据 df <- structure(list(GroupsA = c("G1", "G1", "G1", "G1", "G1", "G2", "G2", "G2", "G2", "G3", "G3", "G3", "G4", "G4", "G5"), GroupsB = c("G2", "G3", "G4", "G5", "G6", "G3", "G4", "G5", "G6", "G4", "G5", "G6", "G5", "G6", "G6")), class = "data.frame", row.names = c(NA, -15L )) list1 <- c("G1","G3") list2 <- c("G2") list3 <- c("G4","G5","G6") df <- df %>% mutate( # 匹配GroupsA所属列表 list_a = case_when( GroupsA %in% list1 ~ "list1", GroupsA %in% list2 ~ "list2", GroupsA %in% list3 ~ "list3" ), # 匹配GroupsB所属列表 list_b = case_when( GroupsB %in% list1 ~ "list1", GroupsB %in% list2 ~ "list2", GroupsB %in% list3 ~ "list3" ), # 拼接成Lists列 Lists = paste(list_a, list_b, sep = "&") ) %>% # 移除中间列(可选) select(-list_a, -list_b) print(df)
方法2:基础R实现
无需额外包,通过自定义函数实现映射:
# 加载数据 df <- structure(list(GroupsA = c("G1", "G1", "G1", "G1", "G1", "G2", "G2", "G2", "G2", "G3", "G3", "G3", "G4", "G4", "G5"), GroupsB = c("G2", "G3", "G4", "G5", "G6", "G3", "G4", "G5", "G6", "G4", "G5", "G6", "G5", "G6", "G6")), class = "data.frame", row.names = c(NA, -15L )) list1 <- c("G1","G3") list2 <- c("G2") list3 <- c("G4","G5","G6") # 创建映射函数 get_list_name <- function(x) { if (x %in% list1) return("list1") if (x %in% list2) return("list2") if (x %in% list3) return("list3") } # 生成Lists列 df$Lists <- mapply(function(a, b) paste(get_list_name(a), get_list_name(b), sep = "&"), df$GroupsA, df$GroupsB) print(df)
方法3:映射表关联法(适合多列表场景)
先构建分组与列表名的映射表,再通过合并关联,扩展性更强:
# 加载数据 df <- structure(list(GroupsA = c("G1", "G1", "G1", "G1", "G1", "G2", "G2", "G2", "G2", "G3", "G3", "G3", "G4", "G4", "G5"), GroupsB = c("G2", "G3", "G4", "G5", "G6", "G3", "G4", "G5", "G6", "G4", "G5", "G6", "G5", "G6", "G6")), class = "data.frame", row.names = c(NA, -15L )) # 构建映射表 map_df <- data.frame( group = c(list1, list2, list3), list_name = c(rep("list1", length(list1)), rep("list2", length(list2)), rep("list3", length(list3))) ) # 关联GroupsA和GroupsB的列表名 df <- merge(df, map_df, by.x = "GroupsA", by.y = "group", all.x = TRUE) %>% rename(list_a = list_name) %>% merge(map_df, by.x = "GroupsB", by.y = "group", all.x = TRUE) %>% rename(list_b = list_name) %>% mutate(Lists = paste(list_a, list_b, sep = "&")) %>% select(GroupsA, GroupsB, Lists) %>% # 恢复原顺序(可选) arrange(match(GroupsA, c("G1","G2","G3","G4","G5")), match(GroupsB, c("G2","G3","G4","G5","G6"))) print(df)
内容的提问来源于stack exchange,提问作者chippycentra
相关产品推荐
相关产品推荐

