Вместо того, чтобы строить фрейм данных построчно, что будет очень неэффективно, вы можете настроить фрейм данных с учетом конечного размера. В этом примере вы знаете, что запустите этот процесс три раза, чтобы в итоге получить четыре строки. Сделайте этот фрейм данных первым, чтобы все остальное было проще и быстрее:
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) одного вектора *. Это странная часть. Ему нужна функция с двумя аргументами и одним вектором. Сначала это не имеет смысла. Как он проходит через один вектор с функцией, которой нужны два аргумента? Пример:
#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 также может принимать список, но сначала мы должны достичь мастерства вектора, а затем ввести методы списка.
29.06.2016