如何用R与dplyr批量替换列中TRUE值为列名并生成合并列
优雅的dplyr/tidyverse解决方案
当然有更简洁的tidy风格写法!针对你这种多列布尔型变量转逗号分隔标签的需求,完全不用写循环,用tidyverse的工具链就能轻松搞定,尤其适合你10+列的场景。
先回顾下你的原始数据:
library(tidyverse) df <- tibble( id = c("a", "b", "c"), tired = c(T, F, T), lonely = c(F, F, T), excited = c(F, T, T) )
核心实现代码
核心思路是把宽格式数据转成长格式,过滤出勾选的记录,再按受访者ID合并标签:
df_result <- df %>% # 将所有感受列转为长格式:列名变为feeling,对应值为TRUE/FALSE pivot_longer(-id, names_to = "feeling", values_to = "selected") %>% # 只保留被勾选的感受(即selected为TRUE的行) filter(selected) %>% # 按ID分组,把同一受访者的感受用逗号连接 group_by(id) %>% summarise(feelings = str_c(feeling, collapse = ", ")) %>% # 取消分组(方便后续操作) ungroup() df_result
运行后得到的结果如下(注:你的预期结果里第一行a的excited应为笔误,原始数据中a的excited是FALSE):
# A tibble: 3 × 2 id feelings <chr> <chr> 1 a tired 2 b excited 3 c tired, lonely, excited
方案优势
- 无需循环:不管你有10列还是100列,代码都不用修改,自动适配所有感受列
- 可读性强:每一步都是明确的数据操作逻辑,别人看代码就能立刻理解你的意图
- 扩展性好:如果要调整分隔符(比如改成分号),只需要修改
str_c里的collapse参数;如果想保留原始所有列并新增feelings,可以用下面的写法:
df_with_feelings <- df %>% mutate(feelings = pmap_chr(select(., -id), ~ { # 逐行筛选出值为TRUE的列名,再合并为字符串 names(c(...))[which(c(...))] %>% str_c(collapse = ", ") }))
这个写法用pmap_chr逐行处理,适合需要保留宽表结构的场景,同样不需要手动写循环。
内容的提问来源于stack exchange,提问作者retide
相关产品推荐
相关产品推荐

