-3

In response to some comments received, here´s what I am trying to do:

  1. Replicate an XLS formula that works fine. The below is the beginning of what that XLS formula does
  2. The complete XLS formula basically interpolates input variables along a time horizon (say 120 months). For example if you ONLY input mo 1 (along vector_1) = .25 (along vector_2), mo 2 (along vector_1) = .50 (along vector_2), XLS outputs mo 1 = .25, mo 2 = .50, mos 3-120 = 0. If you ONLY input mo 1 = 2 and month 3 = 4, then XLS interpolates and output is mo 1 = 2, mo 2 = 3, mo 3 = 4, mo 5-120 = 0. If you ONLY input mo 3 = 2, then output is mo 1 = 2, mo 2 = 2, mo 3 = 2, mo 4-120= 0. Etc. This R snippet is only the beginning of this formula
  3. So all I am trying to do below, for now, is assign vector_2 variables along the mos 1-120 time scale, and if the current period in time horizon (vector_1) > period in the 1-120 scale, then a 0 value is returned.

I was worried about posting this, this is difficult to express clearly. And I want to learn enough to be able to do the rest of this on my own. Best way to learn!

I´m new to R and come from Excel/VBA world. I´m slowly converting an Excel formula to R equivalent. Will eventually change this to a function and explore using SEQ instead of this FOR loop. But for now, what am I doing wrong with the below? I don´t understand why I get NA in the 5th position of the output vector and 9 output elements instead of 10.

Code:

n_periods = 10
vector_1 <- c(1,2,3,4)
vector_2 <- c(0.20,0.10,0.05,0.3)
    
a=ifelse(vector_1[1] < 1, 0, vector_2[1])
  for(i in 1:n_periods){
    if(period[i+1] > max(vector_1)){a[i+1]=0} else {a[i+1] = vector_2[i+1]}
  }
a  

The output is below, whereby (i) the 5th position should show a 0 and not NA, (ii) there should be 10 output elements instead of 9 and (iii) I do not understand why I get that error message (output I´m looking for is 0.20 0.10 0.05 0.30 0.00 0.00 0.00 0.00 0.00 0.00):

 Error in if (period[i + 1] > max(vector_1)) { : 
  missing value where TRUE/FALSE needed
> a  
[1] 0.20 0.10 0.05 0.30   NA 0.00 0.00 0.00 0.00 
  • 1
    Note that arrays in R are 1 based. not zero based. So assuming `periods` has length` n_periods` (unclear because that data is not shown here), then you can only use indexes 1 to `n_periods` When you use `period[i+1]` that `i+1` will be greater than `n_periods` for that last iteration. Plus it looks like your `a` vector is only 5 long so when you index outside of that range, you get `NA` in R. – MrFlick May 13 '21 at 06:41
  • 2
    Can you explain what you are trying to do? What is `vector_1`,`vector_2`? Why are you comparing with `max(vector_1)` ? Why the final output should be `0.20 0.10 0.05 0.30 0.00 0.00 0.00 0.00 0.00 0.00`. Also `period` object is undefined in your code. – Ronak Shah May 13 '21 at 06:42
  • Does the following do what you're after: `a <- rep(0, n_periods)` `a[seq_along(vector_2)] <- vector_2`? – Miff May 13 '21 at 08:19
  • Can you also include a case where only mo3 is given, as stated in third example. What would be two vectors in this case? – AnilGoyal May 13 '21 at 09:52
  • And also a case where say mo2 and mo4 are ONLY given? – AnilGoyal May 13 '21 at 09:52
  • Hi. In response to a case where only mo 3 is given, 3rd example above: vector_1 <- c(3), vector_2 <- c(2). So vectors 1 & 2 can have any number of elements (up to n_periods). A case where only mos 2 and 4 are given: vector_1 <- c(2,4) and say vector_2 <- c(10,20), assuming n_period is 50, the output is 10,10, 15, 20 for mos 1-4, and 0 for mos 5-50. I am tempted to post the XLS (if possible on Stack Overflow, I´m new to this too) but then I don´t learn anything if someone else completely solves for me. Also the formula is a bit of a horror. But I am tempted... – Curious Jorge - user9788072 May 13 '21 at 10:12
  • Ok. see the edited answer, please. If you still want to do it in loop, that can also be done. See [this answer](https://stackoverflow.com/a/67380438/2884859) to have some help. By the way your amortisation question was also answered. Check that too – AnilGoyal May 13 '21 at 13:27

1 Answers1

1

In your for-loop I am not getting what is period[i + 1] as there is no object defined period? However, as vectorised operations in base r you can do this achieve your output. One line of the code has been built upon this answer.

n_periods = 10

#ex-1
vector_1 <- c(1,2,3,4)
vector_2 <- c(0.20,0.10,0.05,0.3)

a <- rep(NA, n_periods)
a[vector_1] <- vector_2
a
#>  [1] 0.20 0.10 0.05 0.30   NA   NA   NA   NA   NA   NA

#ex-2
vector_1 <- c(2,3,4)
vector_2 <- c(0.10,0.05,0.3)

a <- rep(NA, n_periods)
a[vector_1] <- vector_2
a[seq_len(min(vector_1) -1)] <- a[min(vector_1)]
a[seq(max(vector_1)+1, n_periods, 1)] <- 0
a
#>  [1] 0.10 0.10 0.05 0.30 0.00 0.00 0.00 0.00 0.00 0.00

#ex-3
vector_1 <- c(3, 5)
vector_2 <- c(10, 30)

a <- rep(NA, n_periods)
a[vector_1] <- vector_2
a[seq_len(min(vector_1) -1)] <- a[min(vector_1)]
a[seq(max(vector_1)+1, n_periods, 1)] <- 0
a <- approx(seq_along(a)[!is.na(a)], a[!is.na(a)], seq_along(a))$y
a
#>  [1] 10 10 10 20 30  0  0  0  0  0

#complete solution check for more typical case
n_periods <- 20
vector_1 <- c(3, 5, 9)
vector_2 <- c(10, 30, 40)

a <- rep(NA, n_periods)
a[vector_1] <- vector_2
a[seq_len(min(vector_1) -1)] <- a[min(vector_1)]
a[seq(max(vector_1)+1, n_periods, 1)] <- 0
a <- approx(seq_along(a)[!is.na(a)], a[!is.na(a)], seq_along(a))$y
a
#>  [1] 10.0 10.0 10.0 20.0 30.0 32.5 35.0 37.5 40.0  0.0  0.0  0.0  0.0  0.0  0.0
#> [16]  0.0  0.0  0.0  0.0  0.0

Created on 2021-05-13 by the reprex package (v2.0.0)

AnilGoyal
  • 25,297
  • 4
  • 27
  • 45
  • 1
    Thank you AnilGoyal! Very elegant answer, works beautifully. Much more elegant than my tortured XLS formula. I was using a FOR loop because it´s intuitively easier for me to grasp and easier to use in parallel with XLS formulas. But I understand a major advantage of R is vectorization and I need spending time understanding it better. THANK YOU!! – Curious Jorge - user9788072 May 13 '21 at 14:15
  • Yes. Loops are good too. But why go for them unless you can't do it directly. `tidyverse` package in `R` is fabulous and you'll forget about XLS as soon as you'll start using it. One [good resource](https://r4ds.had.co.nz/) for learning it. – AnilGoyal May 13 '21 at 14:32