我正在尝试建立R中分期偿还贷款的视图。 我拥有所有组件变量和输入,但是当从中减去上一期分期付款的值时,我无法成功使用SQL的LAG()函数的等效值来减少未清额。
amount_borrowed <- 900
term <- 9
instalments <- 100
start_date <- as.Date('2019-03-01')
end_date <- (start_date + months(term))
date <- data.frame(seq(start_date, end_date, by="months"))
所需的输出:
|--------|------------|---------|
| date | instalment | balance |
|--------|------------|---------|
| Mar-19 | 100 | 900 |
| Apr-19 | 100 | 800 |
| May-19 | 100 | 700 |
| Jun-19 | 100 | 600 |
等等等
我已经尝试了多种方法来实现上述目标,包括创建UDF并使用SQLDF(如下所示),然后在其中使用迭代减法,但这确实很笨拙,我很想不必诉诸SQLDF就像我经常这样做。
SELECT
date,
instament,
balance,
LAG(balance,1) OVER (
PARTITION BY date
ORDER BY date
) next_balance
FROM
mydataframe
任何帮助表示赞赏
编辑
谢谢大家的帮助和指导。 我增加了新的复杂性,这稍微改变了方法,因此也改变了要求。我将在下面显示我的方法。
从本质上讲,我需要将利息和资本付款合并到计算中。 我们将未结余额的2.2%称为利息,并说资本的计算是利息-分期付款。
以下是输入内容:
# inputs
start_date <- as.Date("2019-03-01")
amount <- 250000
instalment <- 750
interest_rate1 <- 0.0220
term <- 35
end_date <- (start_date + years(term))
因此,在贷款开始时,情况如下:
df_one <- data.frame(start_date, instalment = NA , balance = amount, interest = NA, capital = NA)
然后我得出了整个贷款的日期,如下所示:
all_term_dates <- data.frame(seq(start_date, end_date, by="months"))
colnames(all_term_dates)[1] <- "start_date"
然后我删除第一行,因为我已经有了想要的格式,现在只需要重新开始的点即可。
all_dates_start <- data.frame(all_term_dates$start_date[-1])
colnames(all_dates_start)[1] <- "start_date"
然后我将占位符变量放入数据框中以供以后填充
all_dates_start$instalment <- NA
all_dates_start$balance <- NA
all_dates_start$interest <- NA
all_dates_start$capital <- NA
然后我将第一个数据框与日期和占位符合并
df_two <- rbind(df_one, all_dates_start)
..添加以下计算之前
df_two[["interest"]] <-interest_rate1 * lag(df_two$balance)/12
df_two[["capital"]] <- instalment - df_two$interest
df_two[["balance"]] <- lag(df_two$balance) - df_two$capital
df_two[["instalment"]] <- instalment
我的问题如下;
1)我该如何优雅且递归地执行该操作,以使利率继续是利率和以前的余额的函数?
再次感谢您的帮助。仍然对R缺乏经验并希望发展。不怕努力和失败。
答案 0 :(得分:2)
dplyr
软件包实际上具有一个lag()
函数:
df$next_balance <- lag(df$balance)
答案 1 :(得分:2)
我想你可以尝试
data.frame(date, instalments,balance = amount_borrowed - instalments * seq(0, term))
# date instalments balance
#1 2019-03-01 100 900
#2 2019-04-01 100 800
#3 2019-05-01 100 700
#4 2019-06-01 100 600
#5 2019-07-01 100 500
#6 2019-08-01 100 400
#7 2019-09-01 100 300
#8 2019-10-01 100 200
#9 2019-11-01 100 100
#10 2019-12-01 100 0
数据
amount_borrowed <- 900
term <- 9
instalments <- 100
start_date <- as.Date('2019-03-01')
end_date <- (start_date + months(term))
date <- seq(start_date, end_date, by="months")
答案 2 :(得分:1)
我相信您希望上个月的余额与您的SQL解决方案匹配。如果您需要进行任何计算,我还提供了上个月的分期付款。
library(tidyverse)
df <- tibble(
date = c("2019-03-01", "2019-04-01", "2019-05-01", "2019-06-01"),
installment = c(100, 100, 100, 100),
balance = c(900, 800, 700, 600)
)
df <- df %>%
arrange(date) %>% # in case the months were already not ordered
mutate(
date = format(as.Date(date), "%b-%y"), # change format of date
previous_month_installment = lag(installment),
previous_month_balance = lag(balance)
)
head(df)
#> # A tibble: 4 x 5
#> date installment balance previous_month_installme… previous_month_bala…
#> <chr> <dbl> <dbl> <dbl> <dbl>
#> 1 Mar-19 100 900 NA NA
#> 2 Apr-19 100 800 100 900
#> 3 May-19 100 700 100 800
#> 4 Jun-19 100 600 100 700
由reprex package(v0.3.0)于2019-09-15创建
答案 3 :(得分:1)
似乎有一个关于要问什么的问题,但是如果问题是如何滞后一个变量,那么一种简单的方法是在lag
类变量上使用ts
,其中-1表示向前滞后(如果要向后滞后,则忽略-1)。不使用任何软件包。
balance <- ts(seq(900, 0, -100), start = c(2019, 3), freq = 12)
lag(balance, -1)
注意如果要使用软件包,一个陷阱是某些软件包(xts,dplyr)定义了一个lag
函数,该函数相对于R所设置的标准是反向的。至少对于xts它仅适用于xts对象,因此,如果您不在xts对象上使用lag
,但dplyr不仅以相反的方式定义了它,而且可以覆盖lag
泛型,因此它不会造成伤害在其他软件包中使用。因此,如果您从基础R或其他软件包中使用lag
,请确保未
如果问题是如何生成列为所需输出的表,则不需要lag
。通过明智地使用seq
,diff
和cumsum
,我们可以在此处完全避免使用lag
。我们讨论了两组替代假设。
1)(以问题为分期付款),如果我们先计算balance
,则不需要lag
,也不需要问题中显示的日期预计算,因为我们可以得出长度。不使用任何软件包。
# inputs
start_date <- as.Date("2019-03-01")
amount <- 900
installment <- 100
balance = seq(amount, 0, -installment)
data.frame(date = seq(start_date, by = "month", length = length(balance)),
installment = c(-diff(balance), 0),
balance)
2):如果分期付款是矢量,并且总和为初始余额,则:
# inputs
start_date <- as.Date("2019-03-01")
installments <- rep(100, 9)
data.frame(date = seq(start_date, by = "month", length = length(installments) + 1),
installment = c(installments, 0),
balance = sum(installments) - cumsum(c(0, installments)))