Netlogo: ошибка при применении возрастного распределения из CSV-файла

Я только что обнаружил ошибку в своей модели, в которой я создаю совокупность с распределением по размеру домохозяйства и зависимым распределением по возрасту. Моя проблема в том, что моя процедура, кажется, неправильно назначает вероятности для каждого результата при определении возраста. У меня должно быть 16% пожилых людей, но моя модель дает мне 3% (от всего населения).

Я думаю, это связано с внутренним порядком процедуры, так как пожилые люди назначаются в последнюю очередь. См. код ниже.

Процедура определения размера домохозяйства:

to hatch-family ; hatching the rest of the household using percentual distribution of household size in berlin population
  ifelse random-float 1 <= 0.01 [set household-size 6  set dwelling patch-here hatch 5]
  [ifelse random-float 1 <= 0.02 [set household-size 5 set dwelling patch-here hatch 4]
    [ifelse random-float 1 <= 0.06 [set household-size 4  set dwelling patch-here hatch 3]
      [ifelse random-float 1 <= 0.11 [set household-size 3 set dwelling patch-here hatch 2]
        [ifelse random-float 1 <= 0.31 [set household-size 2 set dwelling patch-here hatch 1]
          [ifelse random-float 1 <= 0.49 [set household-size 1 set dwelling patch-here]
          [hatch-family]
  ]]]]]
end

Порядок определения возраста:

to assign-age; assign age depending on household size according to distribution on csv file,
             ;i = the different rows representing different household sizes
  get-age-data
  if household-size = 1 [get-age-breed 1]
  if household-size = 2 [get-age-breed 2]
  if household-size = 3 [get-age-breed 3]
  if household-size = 4 [get-age-breed 4]
  if household-size = 5 [get-age-breed 5]
  if household-size = 6 [get-age-breed 6]
end

to get-age-data ; reading csv file and creating dataset with age distribution of the population
  file-close-all                          ; close all open files
    if not file-exists? "Data/age-dist-breeds.csv"  [
    user-message "No file 'age-dist-breeds' exists!"
    stop
  ]

  file-open "Data/age-dist-breeds.csv"  ; open the file with the turtle data
  set age-data csv:from-file "Data/age-dist-breeds.csv"
  file-close                              ; making sure to close the file
end

to get-age-breed [i]; process for assigning age after distribution for household size i, will repeat itself if no age is assigned in previous run
  let child-var item 1 item i age-data
ifelse (random-float 1 <= child-var)
   [set age random 14 set breed children set age-susceptibility 0.0025]
   [let teen-var item 2 (item i age-data)
     ifelse (random-float 1 <= teen-var)
    [set age 15 + random 4 set breed teens set age-susceptibility 0.005]
    [let adult-var item 3 (item i age-data)
        ifelse ( random-float 1 <= adult-var)
           [let age-susc-var random 49
            set age 20 + age-susc-var set breed adults set age-susceptibility (age-susc-var / 49) * 0.075 + 0.015]
           [let elder-var item 4 (item i age-data)
  ifelse ( random-float 1 <= elder-var )
        [ set age 70 + random 30 set breed elderly set age-susceptibility 0.08]
        [get-age-breed i]
    ]]
  ]
end

Сначала я пытался сделать random-var вместо того, чтобы пересчитывать его для каждого шага, но потом у меня вообще не было пожилых людей.

Может быть, есть лучший способ, чем процедура random-float, для точного определения ненормальных распределений вероятностей?

Благодарен за вклад!


person Johanna    schedule 01.04.2021    source источник


Ответы (3)


Ваша проблема в том, что вы продолжаете рисовать новое случайное число. Это ваша структура кода с отступом, чтобы вы могли видеть свою логику:

to hatch-family
  ifelse random-float 1 <= 0.01
  []
  [ ifelse random-float 1 <= 0.02
    []
    [ ifelse random-float 1 <= 0.06
      []
      [ ifelse random-float 1 <= 0.11
        []
        [ ifelse random-float 1 <= 0.31
          []
          [ ifelse random-float 1 <= 0.49
            []
            [ hatch-family ]
          ]
        ]
      ]
    ]
   ]
end

Таким образом, он рисует число, 1% шанс удовлетворить первое условие, если нет, он рисует другое число и так далее, пока не дойдет до конца. Более того, примерно в половине случаев все повторяется снова, потому что процедура вызывает себя как ложную ветвь финального розыгрыша.

Итак, первый шаг — нарисовать случайное число только один раз и просто сравнить это значение, что будет выглядеть примерно так:

to hatch-family
  let my-draw random-float 1
  ifelse my-draw <= 0.01 []
  [ ifelse my-draw <= 0.02 []
    [ ifelse my-draw <= 0.06 []

Но вы также можете использовать множественный выбор ifelse для очистки кода (при условии, что вы используете текущую версию NetLogo), и это будет выглядеть так:

to hatch-family
  let my-draw random-float 1
  ( ifelse
     my-draw <= 0.01 []
     my-draw <= 0.02 []
     my-draw <= 0.06 []

Обратите внимание на начало (, чтобы NetLogo знал, что ожидается более двух предложений.

Или вы можете использовать расширение rnd, как уже заметил Стив.

person JenB    schedule 02.04.2021
comment
Большое спасибо за такие четкие и подробные советы! Я попробую с переменной my-draw и множественным выбором ifelse. Может ли быть так, что вероятности должны суммироваться? В противном случае я думаю, что вероятность для последних ifelseoptions будет меньше, чем должна (и самая высокая вероятность составляет 0,49, поэтому, если переменная my-draw выше, мне все равно нужно повторить или поставить 0,49 как последнее). Или, может быть, даже можно случайным образом выбрать количество/процент черепах без использования стохастического процесса? - person Johanna; 03.04.2021
comment
Кроме того, моей основной проблемой является файл csv, в котором вероятности для возраста (в зависимости от размера домохозяйства) не всегда имеют порядок наименьшей → наибольшей вероятности, поскольку они различаются между группами размера домохозяйства. Я попытался выполнить эту процедуру с переменной типа my-draw, но результат получился еще более искаженным, чем с тем, как он выглядит сейчас. - person Johanna; 03.04.2021
comment
CSV-файл выглядит следующим образом: размер домохозяйства, ребенок, подросток, взрослый, пожилой человек 1, 0,00100054, 0,0077986, 0,79368047, 0,19752155 2 , 0,04318101, 0,01964421, 0,73665607, 0,20052328 3, 0,20481136, 0,05955396, 0,70036927, 0,0352637 4, 0,3342381515, 0,08080808080808080808080808080808080808080808080808.0,5080808080808080808.0,5,508080808080808080808.0,5,5080808080808080808080808. , 0,09717893, 0,49882736, 0,02021346 6, 0,38585009, 0,11331504, 0,46838842, 0,03245484 Таким образом, в зависимости от размера домохозяйства распределение возрастных групп различается. Также рассмотрим расширение rnd! Как вы думаете, может ли расширение помочь с проблемой заказа csv? - person Johanna; 03.04.2021
comment
Решил! Еще раз спасибо за ваш ответ. - person Johanna; 03.04.2021
comment
Я рад, что вы решили эту проблему, но в будущем, пожалуйста, задавайте только один вопрос на вопрос. Цель StackOverflow — предоставить ресурс, который поможет людям с проблемами кода, а не только для решения ваших. В нынешнем виде мне не совсем понятно, какую проблему вы на самом деле пытались решить - что-то о неправильном чтении файла csv, или что-то о взвешенных случайных ничьях, или что-то еще. - person JenB; 03.04.2021

Итак, я наконец решил это с помощью @JenB. Выкладываю сюда, вдруг кому-то будет интересно.

Теперь код выглядит следующим образом:

Процедура штриховки остальных домохозяйств в соответствии с кумулятивным распределением по размерам домохозяйств:

; hatching the rest of the household using percentual distribution of household size of Berlin population (Zensus Datenbank)
; (nr of households with specific size / total number of households in Berlin, 
; hence the percentage of the total population will be accurate as the population increases with each hatching)
to hatch-family
ask turtles
  [ 
  let my-draw random-float 1
  (ifelse
   my-draw <= 0.01 [set household-size 6 set dwelling patch-here hatch 5]
   my-draw <= 0.03 [set household-size 5 set dwelling patch-here hatch 4]
   my-draw <= 0.09 [set household-size 4 set dwelling patch-here hatch 3]
   my-draw <= 0.20 [set household-size 3 set dwelling patch-here hatch 2]
   my-draw <= 0.51 [set household-size 2 set dwelling patch-here hatch 1]
      my-draw <= 1 [set household-size 1 set dwelling patch-here]
    )
  ]
end

Процедура определения породы и возраста в зависимости от распределения возраста для каждого размера домохозяйства:

(Этот вопрос я решил с помощью команды up-to-n-of вместо random-float, чтобы решить проблему с вероятностями, которые не всегда находятся в порядке от наименьшего до наибольшего)

to assign-age; assign age depending on household size according to distribution on csv file,
             ;second item [i] = the different rows representing different household sizes
  ask turtles [set age 0]
  get-age-data ; reading csv file and naming it age-data
  get-age-breed 1
  get-age-breed 2
  get-age-breed 3
  get-age-breed 4
  get-age-breed 5
  get-age-breed 6
end

to get-age-breed [i]; process for assigning age after distribution for household size i
  let child-var up-to-n-of ((count turtles with [household-size = i]) * item 1 (item i age-data)) (turtles with [household-size = i and age = 0])
  ask child-var [set age random 14 set breed children set age-susceptibility 0.0025]
  let teen-var up-to-n-of (count turtles with [household-size = i] * item 2 item i age-data) (turtles with [household-size = i and age = 0])
  ask teen-var [set age 15 + random 4 set breed teens set age-susceptibility 0.005]
  let elder-var up-to-n-of (count turtles with [household-size = i] * item 4 item i age-data) (turtles with [household-size = i and age = 0])
  ask elder-var [set age 70 + random 30 set breed elderly set age-susceptibility 0.08]
  let adult-var up-to-n-of (count turtles with [household-size = i] * item 3 item i age-data) (turtles with [household-size = i and age = 0])
  ask adult-var [let age-susc-var random 49 set age 20 + age-susc-var set breed adults set age-susceptibility (age-susc-var / 49) * 0.075 + 0.015]
 
end

Спасибо за ваш вклад!

person Johanna    schedule 03.04.2021

Боюсь, я не рассмотрел всю вашу ситуацию, но я думаю, вам следует проверить расширение Rnd, встроенное в NetLogo. Это должно помочь хотя бы в части того, что вы делаете.

person Steve Railsback    schedule 01.04.2021
comment
Спасибо, рассмотрим это! :) - person Johanna; 02.04.2021