如何根据ID从不同列提取对应元素?(R语言)
根据ID匹配提取对应列元素的解决方案
问题背景
数据集包含ID列和名称带ID标识的列,示例数据如下:
data = data.frame(ID = rep(1:3,2), col1 = 1:6, col2 = 7:12, col3 = 13:18) print(data)
目标是根据每行的ID值,从对应的col{ID}列提取元素,生成新列new,预期结果:
data$new = c(1, 8, 15, 4, 11, 18)
尝试过dplyr::get(paste0())和sapply方法,但都返回整列向量而非单个元素,无法得到预期结果。
解决方案
1. Base R 矩阵索引法
这是最简洁高效的方法,通过构造行-列索引矩阵直接提取元素:
# 构造行号与目标列的索引对 data$new <- data[cbind(seq(nrow(data)), match(paste0("col", data$ID), names(data)))]
原理:cbind(seq(nrow(data)), ...)生成每行对应的行号,match(...)把col{ID}列名转换成数据框中的列索引,两者组合成矩阵后,即可精准提取每行对应位置的元素。
2. dplyr 按行处理法
之前的dplyr写法失败是因为默认按列批量处理,加上rowwise()让函数逐行执行:
library(dplyr) data <- data %>% rowwise() %>% mutate(new = get(paste0("col", ID))) %>% ungroup() # 处理完记得取消按行分组,避免后续操作异常
rowwise()会让mutate逐行计算,此时get(paste0("col", ID))会提取当前行对应列的单个元素,而非整列。
3. purrr 逐行映射法
利用purrr的map2函数,将行号和ID配对后逐行提取:
library(purrr) data$new <- map2_dbl(seq(nrow(data)), data$ID, ~ data[.x, paste0("col", .y)])
map2_dbl会遍历每一组行号(.x)和ID(.y),提取对应单元格的数值并返回向量。
错误原因说明
- 原
dplyr写法未加rowwise():mutate默认按列操作,get(paste0("col", ID))会返回所有col1/col2/col3的整列数据,导致重复填充。 - 原
sapply写法存在两个问题:一是函数内错误引用了ID而非参数x,二是未指定对应行号,导致返回整列数据。修正后的sapply写法如下:
data$new <- sapply(seq(nrow(data)), function(i) data[i, paste0("col", data$ID[i])])
内容的提问来源于stack exchange,提问作者Hann
相关产品推荐
相关产品推荐

