我正在尝试将R中的函数应用于每一行,同时使用上一行中函数的输出更新每一行。我知道这是一个满口,但这是一个例子。假设我有数据帧,df:
df<- data.frame(a=c(10,15,20,25,30), b=c(2,4,5,7,10))
我有一个函数funR,它只取了a列和b列之间的差异:
funR<- function(argA, argB){
c<- argA-argB
return(c)
}
现在我想要的简化版本就是让我说我将函数应用到第一行并得到10 - 2 = 8.然后我想用这个输出替换第二行的列a将函数应用于该行,所以不是15 - 4而是8 - 4.然后我将第3行中的20替换为4,依此类推,依此类推。
编辑以显示预期输出:
a b
1 10 2
2 8 4
3 4 5
4 -1 7
5 -8 10
非常感谢任何帮助!
答案 0 :(得分:2)
这实际上是基础R中的单行:
for (i in 1:(nrow(df) - 1)) df$a[i + 1] <- df$a[i] - df$b[i];
df;
# a b
#1 10 2
#2 8 4
#3 4 5
#4 -1 7
#5 -8 10
这里我们在一个简单的a[i+1] = a[i] - b[i]
循环中实现递归关系for
。 for
循环非常快,因为我们会直接覆盖df
中的现有条目。
或者:
df$a <- df$a[1] - cumsum(c(0, df$b))[1:length(df$a)];
df;
# a b
#1 10 2
#2 8 4
#3 4 5
#4 -1 7
#5 -8 10
这是基于扩展的递归关系,您可以在其中看到,例如a[4] = a[1] - (b[1] + b[2] + b[3])
,等等。
答案 1 :(得分:2)
如果您想要保留函数funR
的使用,这是一个更快的版本。
df<- data.frame(a=c(10,15,20,25,30), b=c(2,4,5,7,10))
funR<- function(argA, argB){
n = length(argA)
argC = c(argA[1], argB)
accumdiff <- function(x){
Reduce(function(x1,x2) x1-x2, x, accumulate=TRUE)}
argC = c(argA[1],accumdiff(argC)[c(-1)])
rev(rev(argC)[-1])
}
df$a <- funR(df$a, df$b)
df
# a b
# 1 10 2
# 2 8 4
# 3 4 5
# 4 -1 7
# 5 -8 10
答案 2 :(得分:2)
我们也可以使用accumulate
purrr
执行此操作
library(purrr)
library(dplyr)
df %>%
mutate(a = accumulate(b[-n()], `-`, .init = a[1]))
# a b
#1 10 2
#2 8 4
#3 4 5
#4 -1 7
#5 -8 10