如何在dplyr的mutate函数中引用新列前值生成计算列?
解决依赖前一行结果生成新列的问题
这问题我太懂了!你遇到的核心卡点是:dplyr::mutate默认是整列批量计算的,没法在计算当前行时直接引用同列刚生成的上一行值——毕竟你写lag(c)的时候,新列c还没完全生成,lag根本拿不到刚算出来的前一行结果。
下面给你两种靠谱的解决方案,都能完美实现你要的规则:
方法1:用purrr::accumulate做累积计算(推荐)
accumulate是专门用来处理这种依赖前一个结果的迭代计算的,配合dplyr使用非常丝滑:
library(dplyr) library(purrr) # 你的原始数据 table <- data.frame(a = rep(100, 8), b = seq(from = 0.2, by = 0.1, length.out = 8)) # 生成列c table <- table %>% mutate(c = accumulate( .x = 1:n(), # 遍历每一行的索引 .f = function(prev_result, current_index) { if (current_index == 1) { # 第一行直接计算a*b a[current_index] * b[current_index] } else { # 从第二行开始,用上一行的结果+当前a,再乘当前b (prev_result + a[current_index]) * b[current_index] } } ))
运行后你会得到预期的结果:第一行c=20,第二行c=36,第三行c=54.4,完全符合你的规则。
方法2:用Base R循环(直观易懂)
如果不想加载额外的包,用基础R的循环也能搞定,小数据量下效率完全没问题:
# 你的原始数据 table <- data.frame(a = rep(100, 8), b = seq(from = 0.2, by = 0.1, length.out = 8)) # 初始化c列 table$c <- numeric(nrow(table)) # 第一行赋值 table$c[1] <- table$a[1] * table$b[1] # 从第二行开始循环计算 for (i in 2:nrow(table)) { table$c[i] <- (table$c[i-1] + table$a[i]) * table$b[i] }
这种写法逻辑非常直观,就是逐行处理,直接引用上一行的c值,新手也能一眼看明白。
为啥你之前的代码不行?
你写的mutate(c = (a + ifelse(is.na(lag(c), 0, lag(c)))) * b),问题出在lag(c):当mutate开始计算时,c还是一个不存在的列,所以lag(c)返回的全是NA,ifelse把这些NA转成0后,计算出来的结果完全不符合你的迭代规则——毕竟你需要的是上一行刚生成的c值,而不是0。
内容的提问来源于stack exchange,提问作者user8009353
相关产品推荐
相关产品推荐

