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

如何用dplyr批量提取多列首字符并合并为新列?

问题:批量提取诊断码首字符并拼接成新列

我有一个数据集,包含100个字符型诊断字段,命名为DiagnosisCode1至DiagnosisCode100。多数情况下第一个诊断字段完整,但并非总是如此,序号较高的字段几乎全为NA。我需要提取这些字段的首字符并合并为一个名为OnsetFlags的新列。由于字段数量多,我不想显式引用所有100个字段,希望使用dplyr的starts_with()等辅助函数或DiagnosisCode1:DiagnosisCode100这样的范围来指代。

示例数据

example = structure(list(id = c("1", "2", "3", "4", 
"5", "6", "7"), DiagnosisCode1 = c("2G56.2", 
"2M48.06", "2G56.2", "2G56.0", "2S83.53", "2M23.20", "2S83.53"
), DiagnosisCode2 = c("2G56.0", "2G55.3", "2G56.0", "2G56.2", 
"2Y92.82", "2Z86.43", "2S83.2"), DiagnosisCode3 = c("2Z86.43", 
"2Z86.43", "2Z86.43", "1J98.1", "2V93.8", NA, "2W19"), DiagnosisCode4 = c(NA, 
"2U82.3", NA, "2U80.2", "2U73.8", NA, "2Y92.39"), DiagnosisCode5 = c(NA, 
"2U83.3", NA, NA, NA, NA, "2U56.39")), row.names = c(NA, -7L), class = "data.frame")

期望结果

新增OnsetFlags列,将各诊断列首字符拼接(自动忽略NA值),示例结果如下:

id DiagnosisCode1 DiagnosisCode2 DiagnosisCode3 DiagnosisCode4 DiagnosisCode5 OnsetFlags
1  1          2G56.2          2G56.0         2Z86.43           <NA>           <NA>        222
2  2         2M48.06          2G55.3         2Z86.43          2U82.3          2U83.3      22222
3  3          2G56.2          2G56.0         2Z86.43           <NA>           <NA>        222
4  4          2G56.0          2G56.2          1J98.1          2U80.2           <NA>       2212
5  5         2S83.53         2Y92.82          2V93.8          2U73.8           <NA>        222
6  6         2M23.20         2Z86.43           <NA>           <NA>           <NA>         22
7  7         2S83.53          2S83.2            2W19         2Y92.39         2U56.39      22222

我的尝试

我尝试使用dplyr的across()函数:

# create onset flag array
example = example %>% 
  mutate(OnsetFlags = across(starts_with("DiagnosisCode"), ~ as.character(substr(., 1, 1))
    ))

但这生成了一个包含多个子列的tibble列,我难以将其提取并合并为数据框的一列,感觉这个方法过于复杂,想知道是否有更简便的解决方法。


解决方案

方法1:dplyr原生方案(rowwise() + c_across())

这是dplyr推荐的行级处理方式,c_across()能在rowwise()环境中获取每行指定列的向量,结合substr()提取首字符后,用paste()自动忽略NA并拼接:

library(dplyr)

example <- example %>%
  rowwise() %>%
  mutate(OnsetFlags = paste(substr(c_across(starts_with("DiagnosisCode")), 1, 1), collapse = "", na.rm = TRUE)) %>%
  ungroup()

方法2:基础R结合dplyr(apply()按行处理)

如果不想用rowwise(),可以用apply()直接对诊断列按行操作:

library(dplyr)

example <- example %>%
  mutate(OnsetFlags = apply(select(., starts_with("DiagnosisCode")), 1, function(x) {
    paste(substr(x, 1, 1), collapse = "", na.rm = TRUE)
  }))

方法3:临时列中转(tidyr::unite())

先提取所有诊断列的首字符生成临时列,再合并为目标列后删除临时列:

library(dplyr)
library(tidyr)

example <- example %>%
  mutate(across(starts_with("DiagnosisCode"), ~ substr(., 1, 1), .names = "temp_{.col}")) %>%
  unite(OnsetFlags, starts_with("temp"), sep = "", na.rm = TRUE) %>%
  select(-starts_with("temp"))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 09:37:41