I'm stuck in a task with FOR and IF functions in R data programming

Viewed 74

So currently i'm stuck in a problem around FOR and IF function.

I have a full working code like this:

#my data input
demand.variation=c(1,4,20,23,37)
demand.probability=c(0.81,0.85,0.89,0.93,0.97)
n.month=25

#generating result matrix
result=matrix(0,n.month,2)
colnames(result)=c("Month","Demand")

#filling result matrix with month index and random demand value
result[,1]=1:n.month
random=runif(n.month,0,1)

#return demand value based on random value
for (i in seq_along(random)) {
  if (random[i]>demand.probability[5]) result[i,2]=demand.variation[5]
  else if (random[i]>demand.probability[4]) result[i,2]=demand.variation[4]
  else if (random[i]>demand.probability[3]) result[i,2]=demand.variation[3]
  else if (random[i]>demand.probability[2]) result[i,2]=demand.variation[2]
  else if (random[i]>demand.probability[1]) result[i,2]=demand.variation[1]
  else result[i,2]=0
}

#final result
result

It is fully working with the result:

> result
      Month Demand
 [1,]     1      0
 [2,]     2      0
 [3,]     3      0
 [4,]     4      0
 [5,]     5      0
 [6,]     6      0
 [7,]     7      0
 [8,]     8      0
 [9,]     9      4
[10,]    10      0
[11,]    11      0
[12,]    12     23
[13,]    13     37
[14,]    14      0
[15,]    15      1
[16,]    16      0
[17,]    17      0
[18,]    18      0
[19,]    19      1
[20,]    20     20
[21,]    21      0
[22,]    22      0
[23,]    23      0
[24,]    24      0
[25,]    25      0

The thing is, i have to re-run the same code, but with different length and value of demand.variation and demand.probability, so i will have problem facing dozens variation for those 2 variables since the FOR and IF is manually entered.

My question is how do you generate a flexible code of FOR and IF statement to cover the job of #return demand value based on random value code.

footnote: demand.variation and demand.probability will always have the same vector length, and is correspondingly connected one to another, which means 1st value in demand.variation vector have the probability of the 1st value in demand.probability vector, and so on

demand.variation=c(1,4,20,23,37)
demand.probability=c(0.81,0.85,0.89,0.93,0.97)

I would be very grateful if you can help me on this.

2 Answers

You could just add anothing for() loop counting backward from the number of entries in the demand.variation vector.

for(i in seq_along(random)){
  for(j in seq_along(demand.variation):1){
    if(random[i] > demand.probability[j]){
      result[i,2] <-  demand.variation[j]
    } else {
      result[i,2] <- 0
    }
  }
}

Edit: Clarification:

So I broke what you want into several functions and combined into a master function that can be called for whatever length/combination required:

create.demand.variation <- function(vector){
  return(demand.probability <- c(vector))
}

create.demand.probability <- function(vector){
  return(demand.probability <- c(vector))
}

create.random <- function(n.month){
  return(random <- runif(n.month, 0, 1))
}

create.result <- function(n.month){
  result=matrix(0,n.month,2)
  colnames(result)=c("Month","Demand")
  result[,1]=1:n.month
  return(result)
}

create.random <- function(n.month){
  return(random <- runif(n.month,0,1))
}

get.result <- function(demand.variation, demand.probability, random.vector, result){
  for(i in 1:length(random)){
    k <- length(demand.probability)
    while(k >= 1){
      if(random[i] > demand.probability[k]){
        result[i,2] <- demand.variation[k]
        k <- 0
      } else {
        k <- k - 1
      }
    }
  }
  return(result)
}

master.function <- function(vector.demand, vector.prob, n.month ){
  create.demand.variation(vector.demand) -> demand.variation
  create.demand.probability(vector.prob) -> demand.probability
  create.random(n.month) -> random.vector
  create.result(n.month) -> result
  get.result(demand.variation, demand.probability, random.vector, result) -> result
  return(result)
}

So for the example vectors, you would type:

master.function(c(1,4,20,23,37), c(0.81, 0.85, 0.89, 0.93, 0.97), 25) -> 
result

For me, this produces:

> result
      Month Demand
 [1,]     1      0
 [2,]     2     20
 [3,]     3      0
 [4,]     4      0
 [5,]     5      0
 [6,]     6      0
 [7,]     7      1
 [8,]     8      0
 [9,]     9      4
[10,]    10      0
[11,]    11     20
[12,]    12      0
[13,]    13     23
[14,]    14      0
[15,]    15      0
[16,]    16      0
[17,]    17      0
[18,]    18      0
[19,]    19      0
[20,]    20      0
[21,]    21      0
[22,]    22      0
[23,]    23      0
[24,]    24      0
[25,]    25      1

You are trying to categorize continuous values (in random) by intervals whose limits are given by demand.probability and which should be labeled to values given in demand.variation. This, you can do by the cut() function in R. However, you have to add some additional borders (-Inf, Inf and e.g. the value 0).

replace your big for-loop expression simply by:

result[, 2] <- cut(random, breaks=c(-Inf, demand.probability, Inf), labels=c(0, demand.variation))

You can do it as a function (with seed for reproducibility):

categorize_months <- function(n_months, breaks, labels, seed=42) {
  set.seed(seed)
  random <- runif(n_months, 0, 1)
  months <- 1:n_months
  demands <- cut(random, breaks=c(-Inf, breaks, Inf), labels=c(0, labels))
  df <- data.frame("Month"=months, "Demand"=demands)
  df
}

categorize_months(25, demand.probability, demand.variation, seed=42)
Related