I have the following dataframe:
dat <- tibble::tribble( ~date , ~pct_monthly_return,
2021-01-31, 0.0023,
2021-02-28, 0.01,
2021-03-31, 0.035)
I would like to create a new column called index
which starts at 100 a month before the dataframe starts (i.e. 2020-12-31 in my example). The index of 100 must then be compounded by pct_monthly_return
variable so that I can see how the index grows over time.
The result should produce the following dataframe:
date pct_monthly_return index
2020-12-31 0 100
2021-01-31 0.0023 100.23
2021-02-28 0.01 101.2323
2021-03-31 0.035 104.7754
Compound interest, or 'interest on interest', is calculated using the compound interest formula. The formula for compound interest is A = P(1 + r/n)^nt, where P is the principal balance, r is the interest rate, n is the number of times interest is compounded per time period and t is the number of time periods.
It is calculated by multiplying the first principal amount by one and adding the annual interest rate raised to the number of compound periods subtract one. The total initial amount of your loan is then subtracted from the resulting value. P is principal, I is the interest rate, n is the number of compounding periods.
We can take the cumulative product of the returns expressed as coefficients, i.e. 1 + pct_monthly_return
dat$index = 100 * cumprod(1+dat$pct_monthly_return)
Then to add the header row you described:
rbind(data.frame(date = "2020-12-31", index = 100, pct_monthly_return = 0),
dat)
date index pct_monthly_return
1 2020-12-31 100.0000 0.0000
2 2021-01-31 100.2300 0.0023
3 2021-02-28 101.2323 0.0100
4 2021-03-31 104.7754 0.0350
Sample data
dat <- tibble::tribble( ~date , ~pct_monthly_return,
"2021-01-31", 0.0023,
"2021-02-28", 0.01,
"2021-03-31", 0.035)
Base R:
Use sapply
and cumprod
:
> cbind(dat, index=as.vector(sapply(dat[,-1] + 1, cumprod) * 100))
date pct_monthly_return index
1 2021-01-31 0.0023 100.2300
2 2021-02-28 0.0100 101.2323
3 2021-03-31 0.0350 104.7754
>
Or even better:
> cbind(dat, index=cumprod(1 + dat$pct_monthly_return) * 100)
date pct_monthly_return index
1 2021-01-31 0.0023 100.2300
2 2021-02-28 0.0100 101.2323
3 2021-03-31 0.0350 104.7754
>
Base R solution:
# Import data: df => data.frame
df <- structure(list(date = structure(c(18658L, 18686L, 18717L), class = c(
"Date")), pct_monthly_return = c(0.0023, 0.01, 0.035)), class = "data.frame", row.names = c(NA,
-3L))
# Add new row calculate index: res => data.frame
res <- transform(
rbind(
data.frame(
date = as.Date("2020-12-31"),
pct_monthly_return = 0.000
),
df
),
index = 100 * cumprod(1 + pct_monthly_return)
)
Tidyverse solution:
# Import and initialise package:
library(tidyverse)
# Import tibble: df1 => tibble
df1 <- structure(list(date = structure(c(18658L, 18686L, 18717L), class = c("Date")), pct_monthly_return = c(0.0023, 0.01, 0.035)), row.names = c(NA, -3L),
class = c("tbl_df", "tbl", "data.frame"))
# Calculate answer: res1 => tibble
res1 <- tibble(date = as.Date("2020-12-31"),
pct_monthly_return = 0.000) %>%
bind_rows(., df1) %>%
mutate(index = 100 * cumprod(1 + pct_monthly_return))
data.table solution:
# Import and intialise data.table package:
library(data.table)
# Import data: dat => data.table
dat <- structure(list(date = structure(c(18658, 18686, 18717), class = "Date"),
pct_monthly_return = c(0.0023, 0.01, 0.035)), row.names = c(NA,
-3L), class = c("data.table", "data.frame"),
.internal.selfref = <pointer: 0x000002704fbd1ef0>)
# Add row and calculate index: dat_res => data.table
dat_res <- rbindlist(
list(
dat1 = data.table(
date = as.Date("2020-12-31"),
pct_monthly_return = 0.000
),
dat
)
)[,index := 100 * cumprod(1 + pct_monthly_return),]
This can be done even with a simple while
loop:
#Assuming you'll always want the first date to be the first row of the new data frame
rbind(data.frame(date=dat$date[1], pct_monthly_return = 0), dat)-> dat
index <- c(100)
i <- 2
while (i <=nrow(dat)) {
index[i] <- (1+dat$pct_monthly_return[i])* index[i-1]
i<- i+1
}
dat$index <- index
> dat
date pct_monthly_return index
1 2021-01-31 0.0000 100.0000
2 2021-01-31 0.0023 100.2300
3 2021-02-28 0.0100 101.2323
4 2021-03-31 0.0350 104.7754
Sample data:
dat <- tibble::tribble( ~date , ~pct_monthly_return,
"2021-01-31", 0.0023,
"2021-02-28", 0.01,
"2021-03-31", 0.035)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With