您可以设置数据框以考虑最终大小,而不是逐行构建数据框,这将是非常低效的。在此示例中,您知道您将运行此过程三次,以总共四行结束。首先制作该数据框,以使其余的更容易和更快:
DF2 <- 'row.names<-'(DF[rep(1,4),], NULL)
DF2$Balance <- Reduce(function(x,y) (x - y)*(1+DF2[1,3]), DF2[-1,2], init=DF[1,1], acc=TRUE)
DF2
# Balance Pmt Interest
# 1 25000.00 1500 0.05
# 2 24675.00 1500 0.05
# 3 24333.75 1500 0.05
# 4 23975.44 1500 0.05
自学:Reduce 是如何工作的?
Reduce 是一个更高级别的函数,它以一种需要练习才能掌握的独特方式工作。它包含两个主要部分,1) 具有两个参数的函数和 2) 单个向量*。这就是奇怪的部分。它需要一个具有两个 args 和 一个 向量的函数。起初这没有意义。它如何通过一个需要两个参数的函数的向量?示例:
#one vector
x <- c(2,3,4,5)
#function with two arguments
multiply <- function(a, b) {a * b}
这是一个从 2 到 5 的向量,以及一个简单的函数,它接受两个数字并将它们相乘。 Reduce 将接受这两个对象并执行以下操作:
Reduce(multiply, x) #<- this
#is the same as
ans1 <- multiply(2, 3)
ans2 <- multiply(ans1, 4)
ans3 <- multiply(ans2, 5)
它通过向量c(2,3,4,5) 并获取前两部分(2 和 3)并在它们上调用函数。然后它接受该答案并引入 x (4) 的第三个元素来运行该函数,然后它接受该答案并与第四个元素 (5) 一起运行它。
在您的示例中,我们使用它来处理第一笔余额和付款:
#one vector
x <- c(25000, 1500, 1500, 1500)
#function with two arguments
f <- function(a,b) (a - b)*(1 + 0.05)
让我们看看它在内部做了什么:
Reduce(f, x) #what we did
#internally Reduce did this
ans1 <- (25000 - 1500) * (1 + 0.05)
ans2 <- (ans1 - 1500) * (1 + 0.05)
ans3 <- (ans2 - 1500) * (1 + 0.05)
这为我们提供了所需的过程。这就是我们所做的想法。为了完全完成我们的讨论,我们添加了两个额外的参数来帮助我们获得预期的结果。 accumulate=TRUE 和 init=DF[1,1]。第一个简单地告诉 Reduce 我们想要每个连续的答案,而不仅仅是最后一个。第二个告诉 Reduce 我们想要从什么值开始。展示 init 做了什么:
#Supply vector for function
x <- DF[-1,2]
x
[1] 1500 1500 1500
#We need the initial balance
#init=DF[1,1] does:
[1] 25000 1500 1500 1500
Reduce 也可以采用列表,但我们应该先掌握向量,然后再引入列表方法。