参考前一行计算

时间:2016-01-06 01:15:21

标签: r

我是R的新手,似乎无法掌握如何调用之前的“self”值,在这种情况下是前一个“b”b[-1]

b <- ( ( 1 / 14 ) * MyData$High + (( 13 / 14 )*b[-1]))

显然我需要在那里的某个地方进行第一次计算,但我无法自己解决这个问题。

添加所追求的结果的示例(A = MyData $ High):

  A  b
1 5  NA
2 10 0.7142...
3 15 3.0393...
4 20 4.6079...

2 个答案:

答案 0 :(得分:5)

1)for循环通常人们只会使用一个简单的循环:

MyData <- data.frame(A = c(5, 10, 15, 20))


MyData$b <- 0
n <- nrow(MyData)
if (n > 1) for(i in 2:n) MyData$b[i] <- ( MyData$A[i] + 13 * MyData$b[i-1] )/ 14
MyData$b[1] <- NA

,并提供:

> MyData
   A         b
1  5        NA
2 10 0.7142857
3 15 1.7346939
4 20 3.0393586

2)减少也可以使用Reduce。首先定义一个函数f来执行循环体,然后我们Reduce重复调用它,如下所示:

f <- function(b, A) (A + 13 * b) / 14
MyData$b <- Reduce(f, MyData$A[-1], 0, acc = TRUE)
MyData$b[1] <- NA

给出相同的结果。

这给出了矢量化的外观,但实际上如果你查看Reduce的来源,它会自己进行for循环。

3)过滤器注意问题的形式是一个递归过滤器,系数13/14在A / 14上运行(但A [1]替换为0)我们可以写下面的内容。由于filter返回时间序列,因此我们使用c(...)将其转换回普通向量。实际上,这种方法是向量化的,因为过滤操作是在C中执行的。

MyData$b <- c(filter(replace(MyData$A, 1, 0)/14, 13/14, method = "recursive"))
MyData$b[1] <- NA

再次给出相同的结果。

注意:所有解决方案都假设MyData至少有一行。

答案 1 :(得分:3)

有几种方法可以做到这一点。

第一种方法是一个简单的循环

df <- data.frame(A = seq(5, 25, 5))
df$b <- 0

for(i in 2:nrow(df)){
  df$b[i] <- (1/14)*df$A[i]+(13/14)*df$b[i-1]
}

df
A         b
1  5 0.0000000
2 10 0.7142857
3 15 1.7346939
4 20 3.0393586
5 25 4.6079758

这并没有给出预期答案中给出的确切值,但它足够接近我认为你犯了转录错误。请注意,我们必须假设我们可以将NA中的df$b[1]视为零,或者我们将NA一直放下。

如果您有大量数据或需要这么做,可以通过在C ++中实现代码并从R调用它来提高速度。

第二种方法使用R功能sapply

您在

中提出问题的表单

b_i = (1/14)A_i + b_{i-1}

是递归的,这使得它无法矢量化,但是我们可以做一些数学并发现它等同于

b_i=\frac{1}{14}\sum_{j=1}^{j=i}{\left( \frac{13}{14}\right)^{(i-j)}A_j}

然后我们可以编写一个计算b_i的函数并使用sapply来计算每个元素

calc_b <- function(n,A){
  (1/14)*sum((13/14)^(n-1:n)*A[1:n])
}

df2 <- data.frame(A = seq(10,25,5))
df2$b <- sapply(seq_along(df2$A), calc_b, df2$A)
df2
A         b
1 10 0.7142857
2 15 1.7346939
3 20 3.0393586
4 25 4.6079758

注意:我们需要删除第一行(A = 5),以便计算正确执行。