'How to store values generated randomly within a while loop in R

In the example below we create a landscape with cell values 1 and 2. Then we want to create patches with the ID 3, with a size between 1 and 10 cells and repeat this until there are 50 cells with the patch ID.

How would also store the randomised patch size from each iteration of the loop so I end up with a list of the patch sizes selected.

library(landscapeR)
library(raster)

Test_landscape <- raster(nrows=50, ncols=50, vals=1) # create raster
Test_landscape[Test_landscape[] == 1] <- # will have 20% unsuitable for patch
  sample(
    c(1,2),
    size = length(Test_landscape[Test_landscape[] ==
                                       1]),
    replace  = T,
    prob = c(0.7, 0.2)
  )

while (length(Test_landscape[Test_landscape[] == 3]) < 50) { # repeat patch making until we have 50 cells
  
  size.clusters <- as.numeric(sample(1:10, 1)) # These are the values that I would like to store?
  Test_landscape <-
    makePatch(
      Test_landscape,
      size = size.clusters,
      bgr = 1, # sutiable cells to make a patch
      edge = FALSE,
      rast = TRUE,
      val = 3 # values given to new patch 
    )
}


Solution 1:[1]

Let's start with a set.seed, and also suggest your initial sample isn't having the desired effect, that you'll see if you plot it. When things don't work when I try to combine them, I break them back apart to smaller, working pieces:

library(landscapeR)
library(raster)
set.seed(516)
tst_ls <- raster(nrows = 50, ncols = 50,vals = 1)
ncell(tst_ls)
[1] 2500
tst_12 <- sample(c(1,2), size = ncell(tst_ls), replace = TRUE, prob=c(0.7, 0.2))
tst_ls <- setValues(tst_ls, tst_12)
ncell(tst_ls) * 0.7

[1] 1750
length(which(values(tst_ls) == 1))

[1] 1976
length(which(values(tst_ls) == 2))

[1] 524

Close enough?, as the sample prob was c(0.7, 0.2). It is suggested to make use of makeClass, rather than makePatch, so we'll try that, in the context of your while. We'll perhaps need some empty vals, initialized outside the while loop, then some changes in notation:

patches <- vector(mode = "numeric", length = 18L)
for (i in 1:18) {
  patches[i] <- sample(1:10, 1)
}
> patches
 [1]  1  3  6  8  1  7  6  8  6 10  6 10  4  1  7  8  4  8
> sum(patches)
[1] 104 # so we'll get to 50
while ((freq(tst_ls, value = 3) < 50)) {
  tst_ls <- makeClass(
    context = tst_ls,
    npatch = max(which(cumsum(patches) < 50)), # matches while
    size = patches[1:npatch],
    bgr = 1,
    edge = FALSE,
    rast = TRUE,
    val = 3
  )
}

Leaving this here for some head scratching done in context of < 50. #examining patches

> patches
 [1]  1  3  6  8  1  7  6  8  6 10  6 10  4  1  7  8  4  8
> cumsum(patches)
 [1]   1   4  10  18  19  26  32  40  46  56  62  72  76  77  84  92  96 104

The adjustment to npatch and size brings it into conformity with while, and finally works as I think you wanted. Cool package.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 user438383