1

I'm trying to use the output from a randomisation as the input for the following iteration. So, i've set up a function/loop that randomises the matrix, and if the first element of the new matrix is larger than the first element of the old matrix (F.new > F.old), I want to store the F.new value, and randomise it again.

If it's decreased for three iterations, I want to stop the loop, and return the output. What i'm having trouble with is passing the new output/matrix back to the start of the loop.

random <- function(x, na.rm = FALSE)(rnorm(n=1,x, x*.3))
F_data <- c(1,2,3,4,5,6,7,8,9)
F_00 <- matrix(F_data,nrow=3,ncol=3,byrow=TRUE)

KK <- 1:1e4
Testrun <- function(F_0){
  loop <- 1
  for(i in KK)
  F <- F_0
  F.New <-apply(F_0, c(1,2), random)
  if (F.New[1,1] > F[1,1]){
    print(loop+1)
    return(F.New)
  }
  F <- F.New
}

tt <- Testrun(F_00)
'''
  • 2
    It's easier to help you if you include a simple [reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) with sample input and desired output that can be used to test and verify possible solutions. – MrFlick Nov 30 '21 at 07:38
  • Thanks Mr Flick, just added some reproducible code now :). – OceanColour Nov 30 '21 at 21:46
  • Hi @OceanColour, were you able to figure this out? – Skaqqs Dec 29 '21 at 19:36

1 Answers1

0

I'd suggest not using F as a variable name, as R interprets this as as a logical!

With this seed, it took 5 iterations to reach your criteria. If you wanted to set a max number of iterations to 100 (for example), you could change the while criteria to while(counter<3 | iter<101).

First, set up the code and monitor how it works:

set.seed(99)

random <- function(x, na.rm = FALSE){
  rnorm(n=1, x, x*0.3)
}

fdata <- c(1,2,3,4,5,6,7,8,9)

# Initial data
f <- matrix(fdata, nrow=3, ncol=3, byrow=TRUE)

# Keep track of the matrices created on each iteration
hist <- list(f)
# Count total iterations
iter <- 0
# Count times condition is met
cond.count <- 0

# Monitor counter value in while-iterator
while(cond.count<3){
  # Keep track of iterations
  iter <- iter + 1
  # Randomize input data
  f2 <- apply(f, c(1,2), random)
  # Save the new matrix in a list
  hist[[iter]] <- f2
  # Check if new value is lower than old value
  # If it is, increase counter value
  if(f2[1,1] < f[1,1]){
    cond.count <- cond.count + 1
  }
  # If counter<3, iterator will repeat
  # using new matrix as input
  f <- f2
}

hist
#> [[1]]
#>          [,1]     [,2]     [,3]
#> [1,] 1.064189 2.266315 2.222539
#> [2,] 4.575590 4.455743 6.881324
#> [3,] 7.184440 8.294418 8.016884
#> 
#> [[2]]
#>           [,1]      [,2]     [,3]
#> [1,] 0.6509934 2.7762730 2.222717
#> [2,] 3.5518898 1.1025014 6.067912
#> [3,] 9.1706873 0.7275844 3.819979
#> 
#> [[3]]
#>            [,1]      [,2]     [,3]
#> [1,]  0.7483752 3.4030278 2.371195
#> [2,]  3.8406092 1.0828493 7.072369
#> [3,] 12.1940470 0.6523736 4.603429
#> 
#> [[4]]
#>            [,1]      [,2]     [,3]
#> [1,]  0.6258184 4.8047900 2.462318
#> [2,]  2.2650728 1.2291173 2.203635
#> [3,] 17.3157364 0.6237421 2.716158
#> 
#> [[5]]
#>            [,1]      [,2]     [,3]
#> [1,]  0.5887425 5.2700282 2.256607
#> [2,]  2.3113386 1.2781512 1.177351
#> [3,] 17.7858764 0.3095137 1.591914

Then define as a function:

# Original input data
f <- matrix(fdata, nrow=3, ncol=3, byrow=TRUE)

myfunc <- function(f){
  set.seed(99) #remove this
  cond.count <- 0
  while(cond.count<3){
    f2 <- apply(f, c(1,2), random)
    if(f2[1,1] < f[1,1]){
      cond.count <- cond.count + 1
    }
    f <- f2
  }
  # Return newest matrix when counter>=3
  return(f)
}


# Since we are using the same seed, we'd expect this to be the same as hist[[5]]
myfunc(f)
#>            [,1]      [,2]     [,3]
#> [1,]  0.5887425 5.2700282 2.256607
#> [2,]  2.3113386 1.2781512 1.177351
#> [3,] 17.7858764 0.3095137 1.591914

Created on 2021-12-16 by the reprex package (v2.0.1)
Skaqqs
  • 4,010
  • 1
  • 7
  • 21