在将函数应用于下一行之前,使用函数的输出替换下一行中的值

时间:2018-03-10 15:20:04

标签: r function

我正在尝试将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    

非常感谢任何帮助!

3 个答案:

答案 0 :(得分:2)

这实际上是基础R中的单行:

方法1:

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]循环中实现递归关系forfor循环非常快,因为我们会直接覆盖df中的现有条目。

方法2

或者:

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