You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R语言中根据列值将列名粘贴到新列(优先用dplyr)

使用dplyr实现行级多列匹配后的列名合并

需求说明

当数据框中以susp开头的列值为1时,将对应列名合并到新列susp_dx中;若同一行有多个符合条件的列,用逗号分隔列名。

示例数据

practice <- data.frame(record_id = 1:5,
                       susp_inflamm = c(1, 0, 0, 1, 0),
                       susp_bacteria = c(1, 0, 0, 0, 0),
                       susp_virus = c(0, 1, 0, 0, 0),
                       susp_fungus = c(0, 0, 1, 0, 0))

错误代码分析

  1. base R代码问题:

    practice$susp_dx <- names(practice[,c(2:5)])[which(practice[,c(2:5)] == 1)]
    

    which(practice[,2:5]==1)返回的是整个子数据框中值为1的全局索引(按列优先),不是按行匹配的结果,导致返回的列名数量与行数不匹配,无法正确赋值。

  2. dplyr代码问题:

    susp_practice <- practice %>% 
      mutate(susp_dx = ifelse(where(is.double) & (starts_with("susp")) == 1), names(.), 0))
    
    • starts_with是列选择器,必须配合select/pick等函数使用,不能直接作为条件判断
    • 未实现行级逻辑处理,无法针对每行单独筛选符合条件的列名
    • ifelse语法错误,括号不匹配

可行解决方案

方案1:dplyr + stringr(推荐,直观易读)

利用rowwise()实现行级操作,结合c_across()和pick()筛选目标列:

library(dplyr)
library(stringr)

practice <- practice %>%
  rowwise() %>% # 开启行级处理模式
  mutate(
    susp_dx = str_c(
      # 获取所有susp开头的列名,筛选出当前行值为1的列名
      names(pick(starts_with("susp")))[c_across(starts_with("susp")) == 1],
      collapse = ", " # 用逗号分隔多个列名
    )
  ) %>%
  ungroup() # 关闭行级模式,恢复默认向量操作

# 输出结果
print(practice)

执行后结果:

record_id susp_inflamm susp_bacteria susp_virus susp_fungus               susp_dx
1         1            1             1          0           0 susp_inflamm, susp_bacteria
2         2            0             0          1           0          susp_virus
3         3            0             0          0           1         susp_fungus
4         4            1             0          0           0        susp_inflamm
5         5            0             0          0           0                     

方案2:dplyr + purrr(无需行级模式,效率更高)

利用pmap_chr()实现逐行处理,适合大数据量场景:

library(dplyr)
library(purrr)
library(stringr)

practice <- practice %>%
  mutate(
    susp_dx = pmap_chr(
      select(., starts_with("susp")), # 传入所有susp开头的列
      ~ str_c(names(c(...))[c(...) == 1], collapse = ", ")
    )
  )

补充:base R替代方案

如果需要base R实现,可使用apply()逐行处理:

susp_cols <- grep("^susp", names(practice), value = TRUE)
practice$susp_dx <- apply(practice[, susp_cols], 1, function(x) {
  paste(names(x)[x == 1], collapse = ", ")
})

内容的提问来源于stack exchange,提问作者Farah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 09:53:20