根据R中的名义值计算实际美元价值

时间:2018-04-09 20:48:07

标签: r for-loop

我有一个包含一些变量的数据集

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)

计划A的美元价值从名义转换为实际的公式如下:

  • 第1期的实际价值:10*(1.014^0.5)*(1.012^1)*(1.012^0.25)

  • 第2期的实际价值:20*(1.012^1)*(1.012^0.25)

  • 第3期的实际价值:30*(1.012^0.25)

我想使用其他函数在超过1000个不同计划的数据集上执行此操作,而不是编写for循环。

感谢您的帮助!

5 个答案:

答案 0 :(得分:2)

使用Base R:我们也可以使用tidyverse

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

答案 1 :(得分:2)

不需要循环。使用data.table包,您可以按组计算累计通货膨胀,并将结果乘以成本:

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

基于@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

答案 2 :(得分:1)

这是一个tidyverse解决方案。我认为我理解所解释的逻辑,即更大的计划周期更新,因此inflation ^ plan_elapsed1的术语越少越好。在这里,我们arrange获取按plan然后plan_period排序的行,然后使用cumprod制作正确的术语,将cost乘以。 / p>

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

reprex package(v0.2.0)创建于2018-04-09。

答案 3 :(得分:1)

考虑by内部sapply调用运行条件产品:

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

答案 4 :(得分:0)

不确定我是否误解了这个问题,但为这个数据写一个for循环似乎相当简单。

chkconfig NetworkManager off
service NetworkManager stop

希望这有用!