如何用dplyr合并名称含指定字符串的列值?(tidyverse方案)
解决方案:用dplyr批量拼接指定列的非NA值
要自动筛选列名含“Games”的列,并逐行拼接非NA值,推荐使用rowwise() + c_across()的组合,配合stringr::str_c()处理拼接,具体代码如下:
library(tidyverse) # 处理示例数据 test <- as_tibble(data.frame( `ID` = c("1","2","3"), `Gender` = c("Female","Male","Non-Binary"), `Games_Chess`=c("Chess",NA,"Chess"), `Games_Clue`=c("Clue",NA,NA), `Games_Scrabble`=c("Scrabble",NA,"Scrabble") )) # 生成拼接列 test <- test %>% rowwise() %>% # 选中所有含"Games"的列,去掉NA后用分号拼接 mutate(Games = str_c(na.omit(c_across(contains("Games"))), collapse = "; ")) %>% ungroup() %>% # 把全NA行的空字符串转为NA mutate(Games = na_if(Games, ""))
运行后得到的结果完全符合期望输出:
# A tibble: 3 × 6 ID Gender Games_Chess Games_Clue Games_Scrabble Games <chr> <chr> <chr> <chr> <chr> <chr> 1 1 Female Chess Clue Scrabble Chess; Clue; Scrabble 2 2 Male NA NA NA NA 3 3 Non-Binary Chess NA Scrabble Chess; Scrabble
为什么你的尝试失败了?
- 尝试1错误原因:
case_when()是用于逐元素的条件判断,你在其中使用的.x是未定义对象,且未正确选中目标列,逻辑上不适合处理整行多列的拼接场景。 - 尝试2错误原因:
grepl("Games", .)会把整个数据框当作字符向量处理,返回结果长度与数据框列数一致,而非每行一个值;paste(., collapse = ";")会把整个数据框内容拼接成一个长字符串,导致新列长度与原数据行数不匹配,触发报错。
关键知识点说明
contains("Games"):dplyr的选择器,能自动匹配列名包含指定字符串的列,实现通用筛选,无需手动列名。rowwise():让后续mutate()按行处理数据,确保每一行的拼接独立进行。c_across():在rowwise环境下,将选中的列合并为一个向量,方便逐行处理。na.omit():过滤向量中的NA值,避免拼接后出现多余分号。na_if(Games, ""):当某一行所有Games列都是NA时,拼接结果为空字符串,这里将其转为NA,符合期望输出。
内容的提问来源于stack exchange,提问作者Mary Rachel
相关产品推荐
相关产品推荐

