如何在R语言中对多列(超过两列)使用union函数?
问题:提取data.frame多列中的唯一值
需要比较data.frame中的列,识别多列里的唯一值。将多个体数据从长格式转宽格式后,想获取每个个体的所有唯一值。示例数据如下:
df <- data_frame(ID=rep(1:10,3), Value = as.character(rep(list("A1,B7,B11,C2","A1,B5,B8,D3",""),10)))
已编写的代码仅能处理生成的前两列,不确定如何纳入第三列(或更多列,通常有5列及以上):
df %>% mutate(across(Value, ~na_if(., ""))) %>% within({time <- ave(ID, list=ID, FUN=seq_along)}) %>% pivot_wider(id_cols="ID",names_from="time",names_prefix="Value",values_from="Value") %>% rowwise() %>% mutate(Value = union( str_split(Value1, ",", simplify = TRUE), str_split(Value2, ",", simplify = TRUE) ) |> str_c(collapse = ", "))
曾考虑用循环将新列与前一次循环的输出对比,但希望找到更简便的方法。
解决方法
可以用c_across()配合tidyverse的函数统一处理所有目标列,无需手动指定列名,适用于任意数量的列:
library(tidyverse) df <- tibble(ID=rep(1:10,3), Value = as.character(rep(list("A1,B7,B11,C2","A1,B5,B8,D3",""),10))) df %>% # 把空字符串转为NA mutate(Value = na_if(Value, "")) %>% # 按ID分组,生成时间序号 group_by(ID) %>% mutate(time = row_number()) %>% ungroup() %>% # 转宽格式 pivot_wider(id_cols = ID, names_from = time, names_prefix = "Value", values_from = Value) %>% rowwise() %>% # 处理所有Value开头的列:过滤NA、拆分字符串、去重 mutate( # 先存为列表格式,保留向量结构 unique_values = list( c_across(starts_with("Value")) %>% discard(is.na) %>% str_split(",") %>% flatten_chr() %>% unique() ) ) %>% # 可选:将列表转为逗号分隔的字符串 mutate(unique_values_str = str_c(unique_values, collapse = ", ")) %>% ungroup()
关键步骤说明
c_across(starts_with("Value")):一次性选中所有以Value开头的列,不管后续新增多少列都能自动适配discard(is.na):过滤掉空字符串转成的NA值,避免拆分出空内容str_split(",") %>% flatten_chr():把所有列的字符串拆分后合并成一维向量unique():对合并后的向量去重,得到每个个体的所有唯一值
内容的提问来源于stack exchange,提问作者beanie42
相关产品推荐
相关产品推荐

