R - 使用ifelse语句在不同列上分配数字的份额

Thi*_*dge 6 if-statement r mutated dplyr

我有以下数据集:

observation <- c(1:10)
pop.d.rank  <- c(1:10)
cost.1  <- c(101:110)
cost.2  <- c(102:111)
cost.3  <- c(103:112)
all <- data.frame(observation,pop.d.rank,cost.1, cost.2, cost.3) 
Run Code Online (Sandbox Code Playgroud)

我想在三年内分配以下金额:

annual.investment <- 500
Run Code Online (Sandbox Code Playgroud)

我可以使用以下脚本在第一年执行此操作:

library(dplyr)

all <- all %>%  
 mutate(capital_allocated.5G = diff(c(0, pmin(cumsum(cost), annual.investment)))) %>%
 mutate(capital_percentage.5G = capital_allocated.5G / cost * 100) %>%
 mutate(year = ifelse(capital_percentage.5G >= 50, "Year.1",0))
Run Code Online (Sandbox Code Playgroud)

但是当我第二年尝试这样做时,考虑到前一年的投资,代码不起作用.这是我尝试在mutate循环中放置一个ifelse语句,以便它不会覆盖前一年分配的钱:

all <- all %>%  
 mutate(capital_allocated.5G = ifelse(year == 0, diff(c(0, pmin(cumsum(cost), annual.investment))), 0) %>%
 mutate(capital_percentage.5G = capital_allocated.5G / cost * 100) %>%
 mutate(year = ifelse(capital_percentage.5G >= 50, "Year.2",0))
Run Code Online (Sandbox Code Playgroud)

我希望数据看起来如下所示,其中分配的金额首先发送到上一年未完成100%的任何行.

capital_allocated.5G <- c(101, 102, 103, 104, 105, 106, 107, 108, 109, 55)
capital_percentage.5G <- c(100, 100, 100, 100, 100, 100, 100, 100, 100, 50)
year <- c("Year.1", "Year.1","Year.1", "Year.1","Year.1", "Year.2", "Year.2","Year.2", "Year.2","Year.2")
example.output <- data.frame(observation,pop.d.rank,cost,   capital_allocated.5G, capital_percentage.5G, year) 
Run Code Online (Sandbox Code Playgroud)

编辑:cost.1是第1年的成本变量,cost.2是第2年的变量,cost.3是第3年的成本变量

编辑:以前接受的答案的问题

我意识到这最终会为capital_percentage.5G变量分配超过100.我创建了一个可重现的例子.我认为这涉及一些成本随着时间的推移而降低并且一些成本随着时间的推移而增加的事实.

这背后的逻辑是,当投资在一年内完成时,5G移动网络的部署成本会有特定成本,这就是成本列与该时间点相关的成本.一旦这项投资在一年内完成,我希望该函数能够提供capital_percentage.5G 100%,然后在未来几年不再为其分配资金.

如何获得它以使百分比值达到100的限制,并且更多的资本分配不会在以后分配给它?

observation <- c(1:10)
pop.d.rank  <- c(1:10)
cost.1  <- c(101:110)
cost.2  <- c(110:101)
cost.3  <- c(100:91)
all <- data.frame(observation,pop.d.rank,cost.1, cost.2, cost.3) 

capital_allocated.5G <- rep(0,10)   ## initialize to zero
capital_percentage.5G <- rep(0,10)  ## initialize to zero
year <- rep(NA,10)                  ## initialize to NA
all <- data.frame(observation,pop.d.rank,cost.1, cost.2, cost.3,   capital_allocated.5G,capital_percentage.5G,year) 

alloc.invest <- function(df, ann.invest, y) {
  df %>% mutate_(cost=paste0("cost.",y)) %>%
    mutate(capital_percentage.5G = capital_allocated.5G / cost * 100,
           year = ifelse(capital_percentage.5G < 50, NA, year),
           not.yet.alloc = ifelse(capital_percentage.5G < 100,cost-capital_allocated.5G,0),
           capital_allocated.5G = capital_allocated.5G +     ifelse(capital_percentage.5G < 100,diff(c(0, pmin(cumsum(not.yet.alloc), ann.invest))), 0),
       capital_percentage.5G = capital_allocated.5G / cost * 100,
       year = ifelse(is.na(year) & capital_percentage.5G >= 50, paste0("Year.",y), year)) %>%
select(-cost,-not.yet.alloc)
}

annual.investment <- 500
all <- alloc.invest(all,annual.investment,1)
print(all)
all <- alloc.invest(all,annual.investment,2)
print(all)
all <- alloc.invest(all,annual.investment,3)
print(all)
Run Code Online (Sandbox Code Playgroud)

在第3年,在这里的最终投资分配中,capital_percentage.5G突然飙升至110%.

aic*_*hao 5

更新了可能增加或减少的同比成本

对于每年可能减少和增加的不同成本,我们根本不需要检查capital_percentage.5G更新时是否超过100%not.yet.alloc并且capital_allocated.5G:

library(dplyr)
alloc.invest <- function(df, ann.invest, y) {
  df %>% mutate_(cost=paste0("cost.",y)) %>%
    mutate(capital_percentage.5G = capital_allocated.5G / cost * 100,
           year = ifelse(capital_percentage.5G < 50, NA, year),
           not.yet.alloc = cost-capital_allocated.5G,
           capital_allocated.5G = capital_allocated.5G + diff(c(0, pmin(cumsum(not.yet.alloc), ann.invest))),
           capital_percentage.5G = capital_allocated.5G / cost * 100,
           year = ifelse(is.na(year) & capital_percentage.5G >= 50, paste0("Year.",y), year)) %>%
    select(-cost,-not.yet.alloc)
}
Run Code Online (Sandbox Code Playgroud)

使用新的成本数据:

observation <- c(1:10)
pop.d.rank  <- c(1:10)
cost.1  <- c(101:110)
cost.2  <- c(110:101)
cost.3  <- c(100:91)
Run Code Online (Sandbox Code Playgroud)

像以前一样使用初始值列进行扩充:

capital_allocated.5G <- rep(0,10)   ## initialize to zero
capital_percentage.5G <- rep(0,10)  ## initialize to zero
year <- rep(NA,10)                  ## initialize to NA
all <- data.frame(observation,pop.d.rank,cost.1, cost.2, cost.3, capital_allocated.5G,capital_percentage.5G,year) 
Run Code Online (Sandbox Code Playgroud)

1年级:

annual.investment <- 500
all <- alloc.invest(all,annual.investment,1)
print(all)
##   observation pop.d.rank cost.1 cost.2 cost.3 capital_allocated.5G capital_percentage.5G   year
##1            1          1    101    110    100                  101             100.00000 Year.1
##2            2          2    102    109     99                  102             100.00000 Year.1
##3            3          3    103    108     98                  103             100.00000 Year.1
##4            4          4    104    107     97                  104             100.00000 Year.1
##5            5          5    105    106     96                   90              85.71429 Year.1
##6            6          6    106    105     95                    0               0.00000   <NA>
##7            7          7    107    104     94                    0               0.00000   <NA>
##8            8          8    108    103     93                    0               0.00000   <NA>
##9            9          9    109    102     92                    0               0.00000   <NA>
##10          10         10    110    101     91                    0               0.00000   <NA>
Run Code Online (Sandbox Code Playgroud)

2年级:

all <- alloc.invest(all,annual.investment,2)
print(all)
##   observation pop.d.rank cost.1 cost.2 cost.3 capital_allocated.5G capital_percentage.5G   year
##1            1          1    101    110    100                  110             100.00000 Year.1
##2            2          2    102    109     99                  109             100.00000 Year.1
##3            3          3    103    108     98                  108             100.00000 Year.1
##4            4          4    104    107     97                  107             100.00000 Year.1
##5            5          5    105    106     96                  106             100.00000 Year.1
##6            6          6    106    105     95                  105             100.00000 Year.2
##7            7          7    107    104     94                  104             100.00000 Year.2
##8            8          8    108    103     93                  103             100.00000 Year.2
##9            9          9    109    102     92                  102             100.00000 Year.2
##10          10         10    110    101     91                   46              45.54455   <NA>
Run Code Online (Sandbox Code Playgroud)

3年级:

all <- alloc.invest(all,annual.investment,3)
print(all)
##   observation pop.d.rank cost.1 cost.2 cost.3 capital_allocated.5G capital_percentage.5G   year
##1            1          1    101    110    100                  100                   100 Year.1
##2            2          2    102    109     99                   99                   100 Year.1
##3            3          3    103    108     98                   98                   100 Year.1
##4            4          4    104    107     97                   97                   100 Year.1
##5            5          5    105    106     96                   96                   100 Year.1
##6            6          6    106    105     95                   95                   100 Year.2
##7            7          7    107    104     94                   94                   100 Year.2
##8            8          8    108    103     93                   93                   100 Year.2
##9            9          9    109    102     92                   92                   100 Year.2
##10          10         10    110    101     91                   91                   100 Year.3
Run Code Online (Sandbox Code Playgroud)

您的代码的最初问题是ifelse只根据条件提供输出开关,而不是costTRUE分支中使用的输入ifelse.因此,cumsum(cost)计算cumsum全部cost而不仅仅是TRUE分支的一部分ifelse.为了解决这个问题,我们可以定义以下函数,然后可以依次为每年执行该函数.

library(dplyr)
alloc.invest <- function(df, ann.invest, y) {
  df %>% mutate(not.yet.alloc = ifelse(capital_percentage.5G < 100,cost-capital_allocated.5G,0),
                capital_allocated.5G = capital_allocated.5G + ifelse(capital_percentage.5G < 100,diff(c(0, pmin(cumsum(not.yet.alloc), ann.invest))), 0),
                capital_percentage.5G = capital_allocated.5G / cost * 100,
                year = ifelse(is.na(year) & capital_percentage.5G >= 50, paste0("Year.",y), year)) %>%
         select(-not.yet.alloc)
}
Run Code Online (Sandbox Code Playgroud)

注意:

  1. 创建一个新的临时not.yet.alloc,我们从中计算cumsum年份分配的结果.
  2. 不需要单独的mutate陈述.
  3. is.na(year)在设置之前还需要检查year.否则,先前year已经标记的将被覆盖.

要使用此功能,必须先用一些初始值增加的输入数据capital_allocated.5G,capital_percentage.5G以及year:

capital_allocated.5G <- rep(0,10)   ## initialize to zero
capital_percentage.5G <- rep(0,10)  ## initialize to zero
year <- rep(NA,10)                  ## initialize to NA
all <- data.frame(observation,pop.d.rank,cost,capital_allocated.5G,capital_percentage.5G,year) 
Run Code Online (Sandbox Code Playgroud)

然后是第1年:

annual.investment <- 500
all <- alloc.invest(all,annual.investment,1)
print(all)
##   observation pop.d.rank cost capital_allocated.5G capital_percentage.5G   year
##1            1          1  101                  101             100.00000 Year.1
##2            2          2  102                  102             100.00000 Year.1
##3            3          3  103                  103             100.00000 Year.1
##4            4          4  104                  104             100.00000 Year.1
##5            5          5  105                   90              85.71429 Year.1
##6            6          6  106                    0               0.00000   <NA>
##7            7          7  107                    0               0.00000   <NA>
##8            8          8  108                    0               0.00000   <NA>
##9            9          9  109                    0               0.00000   <NA>
##10          10         10  110                    0               0.00000   <NA>
Run Code Online (Sandbox Code Playgroud)

而对于2年级:

all <- alloc.invest(all,annual.investment,2)
print(all)
##   observation pop.d.rank cost capital_allocated.5G capital_percentage.5G   year
##1            1          1  101                  101                   100 Year.1
##2            2          2  102                  102                   100 Year.1
##3            3          3  103                  103                   100 Year.1
##4            4          4  104                  104                   100 Year.1
##5            5          5  105                  105                   100 Year.1
##6            6          6  106                  106                   100 Year.2
##7            7          7  107                  107                   100 Year.2
##8            8          8  108                  108                   100 Year.2
##9            9          9  109                  109                   100 Year.2
##10          10         10  110                   55                    50 Year.2  
Run Code Online (Sandbox Code Playgroud)

更新每年更改成本的新要求

如果每年的成本不同,那么函数需要首先重新调整列capital_percentage.5G和可能的year列:

library(dplyr)
alloc.invest <- function(df, ann.invest, y) {
  df %>% mutate_(cost=paste0("cost.",y)) %>%
         mutate(capital_percentage.5G = capital_allocated.5G / cost * 100,
                year = ifelse(capital_percentage.5G < 50, NA, year),
                not.yet.alloc = ifelse(capital_percentage.5G < 100,cost-capital_allocated.5G,0),
                capital_allocated.5G = capital_allocated.5G + ifelse(capital_percentage.5G < 100,diff(c(0, pmin(cumsum(not.yet.alloc), ann.invest))), 0),
                capital_percentage.5G = capital_allocated.5G / cost * 100,
                year = ifelse(is.na(year) & capital_percentage.5G >= 50, paste0("Year.",y), year)) %>%
         select(-cost,-not.yet.alloc)
}
Run Code Online (Sandbox Code Playgroud)

需要注意的是创建另一个临时cost使用mutate_仅仅是为了方便为代价列需要动态地选择基于输入y(否则,我们需要使用mutate_所有的计算,这将是有点混乱).

与用于初始值同样增加更新后的数据capital_allocated.5G,capital_percentage.5Gyear,1年:

annual.investment <- 500
all <- alloc.invest(all,annual.investment,1)
print(all)
##   observation pop.d.rank cost.1 cost.2 cost.3 capital_allocated.5G capital_percentage.5G   year
##1            1          1    101    102    103                  101             100.00000 Year.1
##2            2          2    102    103    104                  102             100.00000 Year.1
##3            3          3    103    104    105                  103             100.00000 Year.1
##4            4          4    104    105    106                  104             100.00000 Year.1
##5            5          5    105    106    107                   90              85.71429 Year.1
##6            6          6    106    107    108                    0               0.00000   <NA>
##7            7          7    107    108    109                    0               0.00000   <NA>
##8            8          8    108    109    110                    0               0.00000   <NA>
##9            9          9    109    110    111                    0               0.00000   <NA>
##10          10         10    110    111    112                    0               0.00000   <NA>
Run Code Online (Sandbox Code Playgroud)

第2年:请注意,上一个资产的50%分配少于分配,因此它year仍然是NA.

all <- alloc.invest(all,annual.investment,2)
print(all)
##   observation pop.d.rank cost.1 cost.2 cost.3 capital_allocated.5G capital_percentage.5G   year
##1            1          1    101    102    103                  102             100.00000 Year.1
##2            2          2    102    103    104                  103             100.00000 Year.1
##3            3          3    103    104    105                  104             100.00000 Year.1
##4            4          4    104    105    106                  105             100.00000 Year.1
##5            5          5    105    106    107                  106             100.00000 Year.1
##6            6          6    106    107    108                  107             100.00000 Year.2
##7            7          7    107    108    109                  108             100.00000 Year.2
##8            8          8    108    109    110                  109             100.00000 Year.2
##9            9          9    109    110    111                  110             100.00000 Year.2
##10          10         10    110    111    112                   46              41.44144   <NA>
Run Code Online (Sandbox Code Playgroud)

3年级:

all <- alloc.invest(all,annual.investment,3)
print(all)
##   observation pop.d.rank cost.1 cost.2 cost.3 capital_allocated.5G capital_percentage.5G   year
##1            1          1    101    102    103                  103                   100 Year.1
##2            2          2    102    103    104                  104                   100 Year.1
##3            3          3    103    104    105                  105                   100 Year.1
##4            4          4    104    105    106                  106                   100 Year.1
##5            5          5    105    106    107                  107                   100 Year.1
##6            6          6    106    107    108                  108                   100 Year.2
##7            7          7    107    108    109                  109                   100 Year.2
##8            8          8    108    109    110                  110                   100 Year.2
##9            9          9    109    110    111                  111                   100 Year.2
##10          10         10    110    111    112                  112                   100 Year.3
Run Code Online (Sandbox Code Playgroud)