Chris1234
Chris1234

Reputation: 73

NetLogo: How do I build a new vector based on randomly chosen values from another vector?

I have a vector 'original' with 10 digits. Now I want to create vector 'adapted' based on 'original'. 'adapted' is supposed to take n random values that are larger than 0 from 'original' in the same position and fill up the rest with 0s, e.g.:

original = [2 3 6 2 0 5 7 2 4 8] adapted = [2 0 0 0 0 5 0 2 0 0]

to go

  let n 3
  let vector-dimension 10

  let original []
  repeat vector-dimension
    [set original lput random 10 original]

   print original

   
   let adapted []

   while [sum (map [ [v1] -> ifelse-value (v1 > 0) [1] [0] ] (adapted)) != n]
     [set adapted (map [ [v1] -> ifelse-value ( (vector-dimension / n) * (100 / vector-dimension) > random-float 100) [v1] [0] ] (original)) ]
    
   print adapted
   
end

This Code works but is slow. How can I do it faster?

Upvotes: 2

Views: 122

Answers (1)

Luke C
Luke C

Reputation: 10301

How about:

to-report report-rand-n [ base n ]
  let indices ( range 0 (length base)) 
  let subset n-of n indices
  let out ( map [ [ i v ] -> ifelse-value ( member? i subset ) [v] [0] ] indices base)
  report out
end

This reporter makes a list of indices (0 through the length of the base passed), then randomly selects n number of those indices to pass to ifelse-value to return either the original value in base (if i is one of the selected indices) or 0.

Testing:

to test
  let original [2 3 6 2 0 5 7 2 4 8]
  print report-rand-n original 3
  print report-rand-n original 3
  print report-rand-n original 5
  print report-rand-n original 5
end

observer> test
[2 0 6 0 0 0 0 0 4 0]
[2 0 0 0 0 0 0 2 0 8]
[2 0 0 0 0 5 0 2 4 8]
[0 0 6 2 0 5 0 0 0 8]

Edit:

to test
  let original [2 3 6 2 0 5 7 2 4 8]
  print word "testing: " original
  print report-rand-n original 3
  
  let few-digits [ 0 0 0 1 0 0 0 ]
  print word "testing: " few-digits
  print report-rand-n few-digits 3
  print ""

end

to-report report-rand-n [ base n ]
  ; create list of indices
  let indices ( range 0 (length base)) 
  
  ; To address point 1) in your comment:
  ; keep only indices that correspond to a value > 0 in base
  let indices-over-zero filter [ i -> item i base > 0 ] indices
  
  ; To address point 2 in your comment:
  ; If the length of indices over zero is less than n, replace n
  ; with the length of indices over zero
  if length indices-over-zero < n [
    set n length indices-over-zero
  ]
  let subset n-of n indices-over-zero
  let out ( map [ [ i v ] -> ifelse-value ( member? i subset ) [v] [0] ] indices base)
  report out
end

Upvotes: 4

Related Questions