在R数据框中按ID匹配列名含指定物质的列并替换值
解决方案:按每行对应物质保留康复年数列的值
方法一:使用tidyverse包(直观易读)
适合偏好管道式操作的新手,步骤清晰:
- 首次使用需安装并加载tidyverse包:
install.packages("tidyverse") library(tidyverse)
- 处理数据:
# 原始数据集 df <- data.frame(id = c(1, 2, 3), substance = c("A,B", "B,C", "C,D"), years_in_recovery.A = c(2, 4, 4), years_in_recovery.B = c(5, 6, NA), years_in_recovery.C = c(8, NA, 10), years_in_recovery.D = c(11, 12, 13)) # 转长格式并提取列名中的物质标识 df_long <- df %>% pivot_longer(cols = starts_with("years_in_recovery"), names_to = "substance_col", values_to = "years") %>% mutate(substance_extracted = str_remove(substance_col, "years_in_recovery\\.")) # 按行匹配物质,保留对应值后转回宽格式 df_processed <- df_long %>% rowwise() %>% mutate(keep = substance_extracted %in% str_split(substance, ",", simplify = TRUE)) %>% filter(keep) %>% ungroup() %>% pivot_wider(names_from = substance_col, values_from = years) # 查看处理结果 print(df_processed)
步骤说明:
pivot_longer:把分散的康复年数列整合为「列名-对应值」的长格式,方便后续匹配。str_remove:从列名中剥离前缀,提取出物质标识(如从years_in_recovery.A得到A)。rowwise()+str_split:按行拆分substance列的逗号分隔字符串,判断当前列的物质是否属于该行的目标物质,只保留匹配的行。pivot_wider:将数据转回原始宽格式,未匹配的列自动填充NA。
方法二:基础R实现(无需额外包)
如果不想安装第三方包,可使用基础R的循环和字符串处理:
# 原始数据集 df <- data.frame(id = c(1, 2, 3), substance = c("A,B", "B,C", "C,D"), years_in_recovery.A = c(2, 4, 4), years_in_recovery.B = c(5, 6, NA), years_in_recovery.C = c(8, NA, 10), years_in_recovery.D = c(11, 12, 13)) # 筛选康复年数列,并提取列名中的物质标识 recovery_cols <- grep("^years_in_recovery", colnames(df), value = TRUE) substance_list <- gsub("years_in_recovery\\.", "", recovery_cols) # 逐行处理数据 for (row_idx in 1:nrow(df)) { # 拆分当前行的物质为向量 current_subs <- strsplit(df$substance[row_idx], ",")[[1]] # 定位不需要保留的列 drop_cols <- recovery_cols[!substance_list %in% current_subs] # 将无关列的值设为NA df[row_idx, drop_cols] <- NA } # 查看结果 print(df)
步骤说明:
grep:筛选出所有以years_in_recovery开头的列。gsub:移除列名前缀,得到纯物质标识。- 循环每行:拆分当前行的目标物质列表,找出不匹配的列并将其值设为
NA。
内容的提问来源于stack exchange,提问作者Fatima
相关产品推荐
相关产品推荐

