Home > Back-end >  multiply one dataframe with another containing growth rates, but have it compound
multiply one dataframe with another containing growth rates, but have it compound

Time:11-23

I have two dataframes - the first contains a single column with 180k rows(i.e. 1x180k) and the other has a single row with 13 columns containing 13 growth rates (i.e. 13x1)

I am trying to multiply these dataframes so that I have a single dataframe that shows the growth of these values overtime.

I can multiply them but I can't work out how to make it compound overtime.

Effectively the dataframe I want will have the existing values in the first column, the second column will have the first column multiplied by the first growth rate, the third column will have the second column multiplied by the second growth rate etc.

Note - my growth rates are in percentages (i.e. 0.05 or 5%)

I have this, but I am not sure how to reflect compounding in it.

LandValuesForecast <- LandValues[,1] %*% (1 t(unlist(GrowthRates[1,])))

CodePudding user response:

You can loop over the columns of both dataframes, applying each rate to the value computed in the previous iteration.

# example data
values <- data.frame(x0 = 1:10 * 100)
rates <- data.frame(r1 = .1, r2 = .01, r3 = .05)

for (i in seq(ncol(rates))) {
  values[[paste0("x", i)]] <- values[, i] * (1   rates[, i])
}

values
     x0   x1     x2       x3
1   100  110  111.1  116.655
2   200  220  222.2  233.310
3   300  330  333.3  349.965
4   400  440  444.4  466.620
5   500  550  555.5  583.275
6   600  660  666.6  699.930
7   700  770  777.7  816.585
8   800  880  888.8  933.240
9   900  990  999.9 1049.895
10 1000 1100 1111.0 1166.550

CodePudding user response:

You can use Reduce() - borrowing @zephryl's data:

values <- data.frame(x0 = 1:10 * 100)
rates <- data.frame(r1 = .1, r2 = .01, r3 = .05)

data.frame(Reduce(`*`, rates   1, init = values, accumulate = TRUE))

     x0 x0.1   x0.2     x0.3
1   100  110  111.1  116.655
2   200  220  222.2  233.310
3   300  330  333.3  349.965
4   400  440  444.4  466.620
5   500  550  555.5  583.275
6   600  660  666.6  699.930
7   700  770  777.7  816.585
8   800  880  888.8  933.240
9   900  990  999.9 1049.895
10 1000 1100 1111.0 1166.550

Or same thing with purrr::accumulate():

library(purrr)

data.frame(accumulate(rates   1, `*`, .init = values))

CodePudding user response:

If I understood your question correctly, I would prefer conversion of dataframes to matrices with multiplication of results using outer function. It is expected to be fast.

library(dplyr) 

df1 <- data.frame(aaa = c(1:10))
df2 <- data.frame(a1 = 1, a2 = 2, a3 = 3)

outer(as.matrix(df1, ncol = 1), 
as.matrix(df2, nrow = 1), 
`*`) %>% as.data.frame

This script will return:

   aaa.1.a1 aaa.1.a2 aaa.1.a3
1         1        2        3
2         2        4        6
3         3        6        9
4         4        8       12
5         5       10       15
6         6       12       18
7         7       14       21
8         8       16       24
9         9       18       27
10       10       20       30
  • Related