Meow
Meow

Reputation: 330

NetLogo - using BehaviorSpace get all turtles locations as the result of each repetition

I am using BehaviorSpace to run the model hundreds of times with different parameters. But I need to know the locations of all turtles as a result instead of only the number of turtles. How can I achieve it with BehaviorSpace?

Currently, I output the results in a csv file by this code:

to-report get-locations
  report (list xcor ycor)
end

to generate-output
  file-open "model_r_1.0_locations.csv"
  file-print csv:to-row get-locations
  file-close
end

but all results are popped into same csv file, so I can't tell the condition of each running.

Upvotes: 2

Views: 435

Answers (1)

Nicolas Payette
Nicolas Payette

Reputation: 14972

Seth's suggestion of incorporating behaviorspace-run-number in the filename of your csv output is one alternative. It would allow you to associate that file with the summary data in your main BehaviorSpace output file.

Another option is to include list reporters as "measures" in your behavior space experiment definition. For example, in your case:

map [ t -> [ xcor ] of t ] sort turtles
map [ t -> [ ycor ] of t ] sort turtles

You can then parse the resulting list "manually" in your favourite data analysis language. I've used the following function for this before, in Julia:

parselist(strlist, T = Float64) = parse.(T, split(strlist[2:end-1]))

I'm sure you can easily write some equivalent code in Python or R or whatever language you're using.

In the example above, I've outputted separate lists for the xcor and the ycor of turtles. You could also output a single "list of lists", but the parsing would be trickier.


Edit: How to do this using the csv extension and R

Coincidentally, I had to do something similar today for a different project, and I realized that a combination of the csv extension and R can make this very easy.

The general idea is the following:

  • In NetLogo, use csv:to-string to encode list data into a string and then write that string directly in the BehaviorSpace output.

  • In R, use purrr::map and readr::read_csv, followed by tidyr::unnest, to unpack everything in a neat "one observation per row" dataframe.

In other words: we like CSV, so we put CSV in our CSV so we can parse while we parse.

Here is a full-fledged example. Let's say we have the following NetLogo model:

extensions [ csv ]

to setup
  clear-all
  create-turtles 2 [ move-to one-of patches ]
  reset-ticks
end

to go
  ask turtles [ forward 1 ]
  tick
end

to-report positions
  let coords [ (list who xcor ycor) ] of turtles
  report csv:to-string fput ["who" "x" "y"] coords
end

We then define the following tiny BehaviorSpace experiment, with only two repetitions and a time limit of two, using our positions reporter as an output:

enter image description here

The R code to process this is pleasantly straightforward:

library(tidyverse)

df <- read_csv("experiment-table.csv", skip = 6) %>%
  mutate(positions = map(positions, read_csv)) %>%
  unnest()

Which results in the following dataframe, all neat and tidy:

> df
# A tibble: 12 x 5
   `[run number]` `[step]`   who      x        y
            <int>    <int> <int>  <dbl>    <dbl>
 1              1        0     0  16     10     
 2              1        0     1  10     -2     
 3              1        1     1   9.03  -2.24  
 4              1        1     0 -16.0   10.1   
 5              1        2     1   8.06  -2.48  
 6              1        2     0 -15.0   10.3   
 7              2        0     1 -14      1     
 8              2        0     0  13     15     
 9              2        1     0  14.0   15.1   
10              2        1     1 -13.7    0.0489
11              2        2     0  15.0   15.1   
12              2        2     1 -13.4   -0.902 

The same thing in Julia:

using CSV, DataFrames
df = CSV.read("experiment-table.csv", header = 7)
cols = filter(col -> col != :positions, names(df))
df = by(df -> CSV.read(IOBuffer(df[:positions][1])), df, cols)

Upvotes: 5

Related Questions