ana_gg
ana_gg

Reputation: 370

Create ranges of different lengths in R using for and while loops

I want to make a loop in R that as a result saves a range whose minimum size is 1000 (initial binLength) and increases its size by 10 points (stepSize) each time the condition is not met. I send the script that I have but I am not getting the result I want.

set.seed(123)

newbins = seq(0,5000,1000)
binLength = 1000
stepSize = 10
blocks=NULL
end = 0


for (b in newbins[1:length(newbins)-1]){
  tempBP = 0
  tempBP_new = 0
  start = end +1
  end = binLength
  while (sum(tempBP_new-tempBP) < 0.40){
    tempBP_new = tempBP
    tempBP_new = runif(1)*0.5
    binLength = binLength + stepSize
    blocks = rbind(blocks,c(start, end))
  }
}
blocks

The output of the script is:

      [,1] [,2]
 [1,]    1 1000
 [2,]    1 1000
 [3,]    1 1000
 [4,]    1 1000
 [5,] 1001 1040
 [6,] 1041 1050
 [7,] 1041 1050
 [8,] 1041 1050
 [9,] 1051 1080
[10,] 1051 1080
[11,] 1051 1080
[12,] 1081 1110
[13,] 1081 1110
[14,] 1081 1110
[15,] 1081 1110
[16,] 1081 1110

But I want something like for example

   1 1000
1001 2040
2041 3050
3050 5000

In other words, each range must be at least 1000 and the loop has to end when it reaches 5000. I also don't understand why I have the same result several times in the loop. Do you have any ideas? Thanks a lot!

Upvotes: 2

Views: 446

Answers (2)

marcguery
marcguery

Reputation: 586

I modified the end of the interval at each iteration and not your minimal length which should remain constant. I also simplified your code by removing useless lists or function calls. The reason you obtain the same results is because you increment your table in the while loop and not when it is finished. Also, I don't know if you want the start or the end of the interval to be below 5000. Regardless this should be relatively easy to fix from there.

set.seed(123)

binLength = 1000
stepSize = 10
blocks = NULL
end = 0

while (end + 1 < 5000){
  tempBP = 0
  tempBP_new = 0
  start = end + 1
  end = end + binLength
  while (tempBP_new - tempBP < 0.40){
    tempBP_new = tempBP
    tempBP = runif(1) * 0.5
    end = end + stepSize
    }
  blocks = rbind(blocks, c(start, min(5000, end)))
  }
blocks
     [,1] [,2]
[1,]    1 1060
[2,] 1061 2510
[3,] 2511 4270
[4,] 4271 5000

Edit: According to the comments, I modified the code to prevent the end of interval to exceed 5000.

Upvotes: 2

Patrick Bormann
Patrick Bormann

Reputation: 749

I'm not really sure what your output should be despite you wrote it.

But if you delete the seed you would see that the output of your vector is strongly dependent of the runif function, thus you dont get a fixed result, if that is of your concern.

In addition, when using the browser() function you would see that in every step the value of tempBP_new is under 0.40 by random, thus you generate more than one occurence of: 1 1000 everytime because that is also dependent by runif. Your loop does not know when the temperature will be exceeded and you "rbind" your result in the while loop.

And binding something ina loop which endiing or next move is determined by random will create different ranges

And you are not increasing binLength = binLength + stepSize by thousand, you are only increasing the StepSize.

Is this something more like you wanted it?

    newbins = seq(0,5000,1000)
    binLength = 1000
    stepSize = 10
    blocks=NULL
    end = 1000
    seq_2 <- seq(0, 5, 1)
    start = 1
    
    
    
    for (b in seq_2){
      if (end >= 5000)
         break
      
      tempBP = 0
      tempBP_new = 0
      while (sum(tempBP_new-tempBP) < 0.40){
        tempBP_new = tempBP
        tempBP_new = runif(1)*0.5
        
      }
      blocks = rbind(blocks,c(start, end))
      start = start + binLength + stepSize
      end = binLength+start-1 + (stepSize*b)
    }
    blocks
     [,1] [,2]
[1,]    1 1000
[2,] 1011 2010
[3,] 2021 3030
[4,] 3031 4050

Upvotes: 1

Related Questions