0

I'm trying to assign my breed called "evacuees" their age based on a percentage. The number of evacuees is based on a slider in the interface, meaning that I don't have a fixed population to work with. They have two properties, "sex" and "age", which are both based on a percentage. I assigned the sex the following way:

let women n-of (count evacuees * 0.513) evacuees

ask women [set sex "female"]

ask evacuees [if not member? self women [set sex "male"]]

That works fine if you only have two categories. But when you have more than two (I have five different age groups) this doesn't work anymore. I tried to still use n-of but with if conditions, so that the agents are not drawn from the whole pool of the evacuees, but only the ones that haven't had an age assigned yet:

set men-0-14 n-of (count evacuees with [sex = "male"] * 0.11) evacuees

    ask men-0-14 [set age "0-14"]
    ask evacuees [
      if not member? self men-0-14 [
        set men-15-19 n-of (count evacuees with [sex = "male"] * 0.04) evacuees with [sex = "male" AND 
        not member? self men-0-14]
      ] 
    ]
    ask men-15-19 [set age "15-19"]
    ask evacuees [
      if not member? self men-0-14 AND not member? self men-15-19 [
        set men-20-39 n-of (count evacuees with [sex = "male"] * 0.26) evacuees with [sex = "male" AND 
        not member? self men-0-14 AND not member? self men-15-19]
      ] 
   ]
   ask men-20-39 [set age "20-39"]

... and so on for all five categories. But in the end I will still have some male evacuees that don't have an age assigned. I think that might be because of the usage of n-of, that it always draws from the whole evacuees, even if using if-conditions. Or it might be a problem of scheduling in NetLogo, that all of the evacuees are still part of the pool because the age group gets assigned definitely when the procedure is finished.

Is there another way to create the five agentsets that have an age assigned based on a certain percentage?

desertnaut
  • 57,590
  • 26
  • 140
  • 166
misch
  • 11
  • 3

1 Answers1

0

Here's a generic solution that lets you assign sexes and age-groups in a nice table format in setup, then applies those percentages of each group to however many turtles you have, and reports on the results. It seems to work.

globals [ sex-percentages age-percentages ]

turtles-own [ sex_code sex_label age_code age_label ]
to setup
  clear-all
  
  let delist []
  ;; assume the percent lists are % of total population desired, code, and label 
  
  set sex-percentages [
      [0.4 "M" "male"   ] 
      [0.6 "F" "female" ]
  ]
  
  set age-percentages [
     [0.2 1 "under 10" ]
     [0.5 2 "11-30"    ]
     [0.2 3 "31-50"    ]
     [0.1 4 "over 50 " ]
  ]
  create-turtles ( 100 + random 20)  [set size 2 set shape "person" setxy random-xcor random-ycor 
    
    set delist assign sex-percentages
    set sex_code first delist
    set sex_label last delist
    set label sex_code
    
    set delist assign age-percentages
    set age_code first delist
    set age_label last delist
    set label age_code

    
    
    
  ]
  report-sexes
  report-ages
  
  reset-ticks
end

to report-sexes
  let sexlist []
  let n count turtles
  ask turtles [ set sexlist lput sex_code  sexlist ]
  let sexes sort remove-duplicates sexlist
  foreach sexes 
   [ x ->  let thiscount length filter [ i -> i = x ] sexlist
     let pct ( 100 * thiscount / n )
     print (word   x " has "  thiscount " of " n " = " precision pct 3  " percent" ) 
  ]
   print "Requested: "
  foreach age-percentages [ x -> print x ]
end

to report-ages
    let agelist []
  let n count turtles
  ask turtles [ set agelist lput age_code  agelist ]
  let ages sort remove-duplicates agelist
  foreach ages
   [ x ->  let thiscount length filter [ i -> i = x ] agelist
     let pct ( 100 * thiscount / n )
     print (word   x " has "  thiscount " of " n " = " precision pct 3  " percent" ) 
  ]
 print "Requested: "
  foreach age-percentages [ x -> print x ]
end

 
  
to-report  assign [ distribution ]
  let chooser random-float 1  ;; returns value in range [0, 0.99999]
  let assigned false
  
  let running_sum  0
  
  ;; set default values in case the code isn't working correctly
  let decode "?"
  let delabel "?"
  
  foreach distribution
  [
      x -> 
      let group-pct item 0 x
      let group-code item 1 x
      let group-label item 2 x
    
      set running_sum ( running_sum + group-pct) 
    
    if ( running_sum > 1) [ print "ERROR - total is over 100%" stop]
    
      if (( assigned = false ) and ( chooser <= running_sum))
         [ set decode group-code
           set delabel group-label
           set assigned true
         ]
  ]
  
  report (list decode delabel )
  
end
Wade Schuette
  • 1,455
  • 1
  • 8
  • 9