在R语言中如何根据另一列的值将数据框多列合并为单列?
基于Step列值合并多列为单列的简洁R语言解法
需求说明
现有数据框df,需根据Step列的取值,将指定列的内容提取到新列AA中,规则如下:
- Step=1时,提取
STA_AA列的值 - Step=2时,提取
INT_AA1列的值 - Step=3时,提取
INT_AA2列的值 - Step=4时,提取
END_AA列的值
最终保留POSITION、Step和AA三列。
输入数据
df <- structure(list(STA_AA = c("A", "A", "A", "A", "A", "A"), INT_AA1 = c("S", "G", "S", "S", "A", "A"), INT_AA2 = c("C", "C", "C", "S", "S", "G"), END_AA = c(NA, NA, "C", "C", "C", "C"), POSITION = c(221L, 221L, 221L, 221L, 221L, 221L), Step = c(1, 2, 3, 4, 1, 2)), row.names = c(NA, 6L), class = "data.frame")
输入数据直观展示:
STA_AA INT_AA1 INT_AA2 END_AA POSITION Step 1 A S C <NA> 221 1 2 A G C <NA> 221 2 3 A S C C 221 3 4 A S S C 221 4 5 A A S C 221 1 6 A A G C 221 2
理想输出
op <- structure(list(POSITION = c(221L, 221L, 221L, 221L, 221L, 221L), Step = c(1, 2, 3, 4, 1, 2), AA = c("A", "G", "C", "C", "A", "A")), row.names = c(NA, 6L), class = "data.frame")
直观展示:
POSITION Step AA 1 221 1 A 2 221 2 G 3 221 3 C 4 221 4 C 5 221 1 A 6 221 2 A
当前循环实现方法
使用foreach循环逐行判断赋值,代码如下:
library(tidyverse) library(foreach) df <- df %>% mutate(AA = NA) foreach(j = 1:nrow(df)) %do% { if (df$Step[j] == 1) { df$AA[j] <- df$STA_AA[j] } if (df$Step[j] == 2) { df$AA[j] <- df$INT_AA1[j] } if (df$Step[j] == 3) { df$AA[j] <- df$INT_AA2[j] } if (df$Step[j] == 4) { df$AA[j] <- df$END_AA[j] } } df <- df %>% select(-STA_AA, -INT_AA1, -INT_AA2, -END_AA)
更简洁的解法
方法1:使用dplyr::case_when
利用case_when按条件批量赋值,无需循环,代码简洁易读:
library(dplyr) df_result <- df %>% mutate(AA = case_when( Step == 1 ~ STA_AA, Step == 2 ~ INT_AA1, Step == 3 ~ INT_AA2, Step == 4 ~ END_AA, TRUE ~ NA_character_ # 处理Step不在1-4范围内的异常情况 )) %>% select(POSITION, Step, AA)
方法2:使用rowwise + pick
通过建立Step与列名的映射关系,动态选取对应列的值,适配列名与Step有固定对应关系的场景:
library(dplyr) # 建立Step到目标列名的映射 col_map <- c("1" = "STA_AA", "2" = "INT_AA1", "3" = "INT_AA2", "4" = "END_AA") df_result <- df %>% rowwise() %>% mutate(AA = pick(all_of(col_map[as.character(Step)])) %>% pull()) %>% ungroup() %>% select(POSITION, Step, AA)
方法3:矩阵索引法(基础R实现)
无需加载额外包,利用矩阵索引直接提取对应位置的值,性能高效:
# 提取需要匹配的目标列 target_cols <- df[, c("STA_AA", "INT_AA1", "INT_AA2", "END_AA")] # 生成索引矩阵:行号为数据框行序号,列号为Step的取值 idx <- cbind(1:nrow(df), df$Step) # 提取对应值并创建AA列 df$AA <- target_cols[idx] # 保留目标列 df_result <- df[, c("POSITION", "Step", "AA")]
以上三种方法均能高效完成需求,避免了循环带来的冗余代码,且在大数据量场景下性能更优。
内容的提问来源于stack exchange,提问作者Dylan1414
相关产品推荐
相关产品推荐

