在R语言中使用for循环在管道中迭代变量的问题
问题描述
我有如下简化数据集:
x_1 <- c(1, NA, 2, 3, NA, 4, 5) x_2 <- c(2, 1, NA, NA, NA, 4, 6) y_1 <- c(2, 4, 6, 8, NA, 10, NA) y_2 <- c(NA, 4, NA, 8, 10, 11, 13) df <- data.frame(x_1, x_2, y_1, y_2) # 数据集输出 # x_1 x_2 y_1 y_2 # 1 1 2 2 NA # 2 NA 1 4 4 # 3 2 NA 6 NA # 4 3 NA 8 8 # 5 NA NA NA 10 # 6 4 4 10 11 # 7 5 6 NA 13
我的目标是合并每组对应的变量(如x和y),并将两组变量值不一致的位置替换为NA。已手动实现单个变量的处理:
df <- df %>% mutate(x = coalesce(x_1, x_2)) %>% mutate(x = ifelse(!is.na(x) & !is.na(x_2) & x != x_2, NA, x)) %>% select(!c(x_1, x_2))
但需要处理21组这样的变量,因此尝试用for循环批量处理:
cols <- c("x", "y") for(i in cols){ var_1 <- paste(i, "1", sep = "_") var_2 <- paste(i, "2", sep = "_") df <- df %>% mutate(i = coalesce(var_1, var_2)) %>% mutate(i = ifelse(!is.na(i) & !is.na(var_2) & i != var_2, NA, i)) %>% select(!c(var_1, var_2)) }
代码可执行,但未生成预期的x、y变量,仅生成值为空的变量i。R能识别var_1和var_2并删除它们,但无法将i识别为迭代器。请问这是什么原因,该如何解决?
问题原因与解决方法
核心原因
- 列名赋值问题:在
mutate(i = ...)中,R会将i当作字面量列名"i",而非迭代变量对应的"x"或"y",所以每次循环都会覆盖名为i的列,最终只留下空值的i。 - 列引用错误:
coalesce(var_1, var_2)中的var_1是字符串(如"x_1"),而非数据框中的列对象,coalesce无法正确识别列值,导致生成空列。
解决方法
方法1:使用.data代词与动态列名赋值
利用dplyr的.data代词引用字符串对应的列,并用!!i :=实现动态列名赋值:
cols <- c("x", "y") for(i in cols){ var_1 <- paste(i, "1", sep = "_") var_2 <- paste(i, "2", sep = "_") df <- df %>% # 动态命名新列,并用.data引用原列 mutate(!!i := coalesce(.data[[var_1]], .data[[var_2]])) %>% # 同样用.data引用列,判断值是否一致 mutate(!!i := ifelse(!is.na(.data[[i]]) & !is.na(.data[[var_2]]) & .data[[i]] != .data[[var_2]], NA, .data[[i]])) %>% # 删除原列 select(!c(var_1, var_2)) }
方法2:使用符号转换(sym + !!)
将字符串转换为R语言的符号,再通过!!强制求值:
cols <- c("x", "y") for(i in cols){ # 将字符串转换为符号 var_1 <- sym(paste(i, "1", sep = "_")) var_2 <- sym(paste(i, "2", sep = "_")) new_var <- sym(i) df <- df %>% mutate(!!new_var := coalesce(!!var_1, !!var_2)) %>% mutate(!!new_var := ifelse(!is.na(!!new_var) & !is.na(!!var_2) & !!new_var != !!var_2, NA, !!new_var)) %>% select(!c(!!var_1, !!var_2)) }
处理后结果
运行上述代码后,得到的df如下,符合预期(值不一致的位置已替换为NA):
x y 1 NA 2 2 1 4 3 2 6 4 3 8 5 NA 10 6 4 NA 7 NA 13
内容的提问来源于stack exchange,提问作者kobue1
相关产品推荐
相关产品推荐

