I have a dataset that contains a few variables
Plan <- c("A","A","A","B","B","B","B")
Plan_Period <- c(1,2,3,1,2,3,4)
Plan_Elapsed_time <- c(0.5,1,0.25,1,0.5,0.3,0.25)
year <- c(2016,2017,2018,2015,2016,2017,2018)
Inflation <- c(1.014,1.012,1.012,1.013,1.012, 1.080,1.020)
Cost <- c(10,20,30,40,40,50,60)
data <- data.frame(Plan, Plan_Period, Plan_Elapsed_time, year, Inflation, Cost)
The formula for converting a dollar value from nominal to real for plan A is as below:
real value for period 1: 10*(1.014^0.5)*(1.012^1)*(1.012^0.25)
real value for period 2: 20*(1.012^1)*(1.012^0.25)
real value for period 3: 30*(1.012^0.25)
I want to use other functions to do this on a dataset with more than 1000 different plans instead of writing a for loop, .
I appreciate your help!
Using Base R: we can use tidyverse too
data=data.frame(Plan,Plan_Period ,Plan_Elapsed_time,year, Inflation,Cost
transform(data,m=Cost*ave(Inflation^Plan_Elapsed_time,Plan,
FUN=function(x)rev(cumprod(rev((x))))))
Plan Plan_Period Plan_Elapsed_time year Inflation Cost m
1 A 1 0.50 2016 1.014 10 10.22103
2 A 2 1.00 2017 1.012 20 20.30045
3 A 3 0.25 2018 1.012 30 30.08960
4 B 1 1.00 2015 1.013 40 41.92150
5 B 2 0.50 2016 1.012 40 41.38352
6 B 3 0.30 2017 1.080 50 51.42179
7 B 4 0.25 2018 1.020 60 60.29778
library(tidyverse)
data%>%
group_by(Plan)%>%
mutate(m=Cost*rev(cumprod(rev(Inflation^Plan_Elapsed_time))))
# A tibble: 7 x 7
# Groups: Plan [2]
Plan Plan_Period Plan_Elapsed_time year Inflation Cost m
<fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 A 1.00 0.500 2016 1.01 10.0 10.2
2 A 2.00 1.00 2017 1.01 20.0 20.3
3 A 3.00 0.250 2018 1.01 30.0 30.1
4 B 1.00 1.00 2015 1.01 40.0 41.9
5 B 2.00 0.500 2016 1.01 40.0 41.4
6 B 3.00 0.300 2017 1.08 50.0 51.4
7 B 4.00 0.250 2018 1.02 60.0 60.3
library(data.table)
setDT(data)[,m:=(Cost*rev(cumprod(rev(Inflation^Plan_Elapsed_time)))),by=Plan][]
Plan Plan_Period Plan_Elapsed_time year Inflation Cost m
1: A 1 0.50 2016 1.014 10 10.22103
2: A 2 1.00 2017 1.012 20 20.30045
3: A 3 0.25 2018 1.012 30 30.08960
4: B 1 1.00 2015 1.013 40 41.92150
5: B 2 0.50 2016 1.012 40 41.38352
6: B 3 0.30 2017 1.080 50 51.42179
7: B 4 0.25 2018 1.020 60 60.29778
There is no need for loops. Using the data.table
package you can calculate the cumulated inflation by group and multiply the result with the cost:
data <- data.frame(
Plan = c("A","A","A","B","B","B","B"),
Plan_Period=c(1,2,3,1,2,3,4),
Plan_Elapsed_time=c(0.5,1,0.25,1,0.5,0.3,0.25),
year=c(2016,2017,2018,2015,2016,2017,2018),
Inflation= c(1.014,1.012,1.012,1.013,1.012, 1.080,1.020),
Cost= c(10,20,30,40,40,50,60)
)
library(data.table)
setDT(data)
data <- data[order(Plan, -Plan_Period)][, Cum_Inflation := cumprod(Inflation^Plan_Elapsed_time), by = Plan][, Real_Cost := Cost * Cum_Inflation]
print(data)
#> Plan Plan_Period Plan_Elapsed_time year Inflation Cost Cum_Inflation Real_Cost
#> 1: A 3 0.25 2018 1.012 30 1.002987 30.08960
#> 2: A 2 1.00 2017 1.012 20 1.015022 20.30045
#> 3: A 1 0.50 2016 1.014 10 1.022103 10.22103
#> 4: B 4 0.25 2018 1.020 60 1.004963 60.29778
#> 5: B 3 0.30 2017 1.080 50 1.028436 51.42179
#> 6: B 2 0.50 2016 1.012 40 1.034588 41.38352
#> 7: B 1 1.00 2015 1.013 40 1.048038 41.92150
Optimized version based on comment by @Sathish:
data <- data.frame(
Plan = c("A","A","A","B","B","B","B"),
Plan_Period=c(1,2,3,1,2,3,4),
Plan_Elapsed_time=c(0.5,1,0.25,1,0.5,0.3,0.25),
year=c(2016,2017,2018,2015,2016,2017,2018),
Inflation= c(1.014,1.012,1.012,1.013,1.012, 1.080,1.020),
Cost= c(10,20,30,40,40,50,60)
)
library(data.table)
setDT(data)[order(Plan, -Plan_Period), real_val := Cost * cumprod( Inflation ^ Plan_Elapsed_time ), by = .(Plan)]
data
#> Plan Plan_Period Plan_Elapsed_time year Inflation Cost real_val
#> 1: A 1 0.50 2016 1.014 10 10.22103
#> 2: A 2 1.00 2017 1.012 20 20.30045
#> 3: A 3 0.25 2018 1.012 30 30.08960
#> 4: B 1 1.00 2015 1.013 40 41.92150
#> 5: B 2 0.50 2016 1.012 40 41.38352
#> 6: B 3 0.30 2017 1.080 50 51.42179
#> 7: B 4 0.25 2018 1.020 60 60.29778
Here is a tidyverse
solution. I think I understand the logic as explained, which is that the larger plan periods are more recent, and so have fewer terms of inflation ^ plan_elapsed1
to multiply by. Here we arrange
to get the rows ordered by plan
and then plan_period
, and then use cumprod
to make the right terms to multiply the cost
by.
library(tidyverse)
data <- tibble(
Plan = c("A","A","A","B","B","B","B"),
Plan_Period = c(1,2,3,1,2,3,4),
Plan_Elapsed_time = c(0.5,1,0.25,1,0.5,0.3,0.25),
year = c(2016,2017,2018,2015,2016,2017,2018),
Inflation = c(1.014,1.012,1.012,1.013,1.012, 1.080,1.020),
Cost = c(10,20,30,40,40,50,60)
)
data %>%
`colnames<-`(str_to_lower(colnames(.))) %>%
mutate(deflate = inflation ^ plan_elapsed_time) %>%
group_by(plan) %>%
arrange(plan, desc(plan_period)) %>%
mutate(
cum_deflate = cumprod(deflate),
real_cost = cost * cum_deflate
) %>%
select(plan:cost, real_cost)
#> # A tibble: 7 x 7
#> # Groups: plan [2]
#> plan plan_period plan_elapsed_time year inflation cost real_cost
#> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 A 3. 0.250 2018. 1.01 30. 30.1
#> 2 A 2. 1.00 2017. 1.01 20. 20.3
#> 3 A 1. 0.500 2016. 1.01 10. 10.2
#> 4 B 4. 0.250 2018. 1.02 60. 60.3
#> 5 B 3. 0.300 2017. 1.08 50. 51.4
#> 6 B 2. 0.500 2016. 1.01 40. 41.4
#> 7 B 1. 1.00 2015. 1.01 40. 41.9
Created on 2018-04-09 by the reprex package (v0.2.0).
Consider by
with inner sapply
call for running conditional product:
by_list <- by(data, data$Plan, function(sub){
sub$RealValue <- sapply(sub$Plan_Period, function(i)
sub$Cost[sub$Plan_Period == i] * prod((sub$Inflation[sub$Plan_Period >= i])^(sub$Plan_Elapsed_time[sub$Plan_Period >= i]))
)
return(sub)
})
finaldata <- do.call(rbind, unname(by_list))
finaldata
# Plan Plan_Period Plan_Elapsed_time year Inflation Cost RealValue
# 1 A 1 0.50 2016 1.014 10 10.22103
# 2 A 2 1.00 2017 1.012 20 20.30045
# 3 A 3 0.25 2018 1.012 30 30.08960
# 4 B 1 1.00 2015 1.013 40 41.92150
# 5 B 2 0.50 2016 1.012 40 41.38352
# 6 B 3 0.30 2017 1.080 50 51.42179
# 7 B 4 0.25 2018 1.020 60 60.29778
Not sure if I misunderstood the question, but it seems fairly straightforward for writing a for-loop for this data.
n<-length(Plan)
for(i in 1:n){
if (Plan[i]=="A" & Plan_Period[i]==1){
print(10*(1.014^0.5)*(1.012^1)*(0.25^1.012))
}
else if (Plan[i]=="A" & Plan_Period[i]==2){
print(20*(1.012^1)*(0.25^1.012))
}
else if (Plan[i]=="A" & Plan_Period[i]==3){
print(30*(1.012^0.25))
}
else {
print(0)
}
}
Hope this is helpful!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.