netlogodata-collectionbehaviorspace

How can I collect the "ids" of directed links using the NetLogo Behavior Space?


We have stored a lot of data as attributes of links in our NetLogo model. When I use the Behavior Space to design experiments and to direct data collection, I specify the "[attribute] of link" to be extracted. However, in the CSV file I cannot see the id of the link, which is an essential to understand the data. How can I collect the ids of links in my results? From what I understand there is no primitive to enable this command.


Solution

  • Whenever you want to extract information from individual agents (including links) using BehaviorSpace, a nice way to do it is to use the csv extension as explained in this answer:

    https://stackoverflow.com/a/52406247/487946

    The general idea is that we can embed csv into our csv, and then use a read_csv-like function in R (or Python or Julia or whatever) to extract the "inner csv" from our BehaviorSpace results.

    In the case of links, it would be useful to include the who number of each end of the link to uniquely identify it. (This is one of the very few cases where I'll advocate using a who number for anything.)

    Let's take this silly example model:

    extensions [ csv ]
    links-own [ attribute ]
    
    to setup
      clear-all
      create-turtles 3 [
        create-links-with other turtles [
          set attribute random-float 1
        ]
      ]
      reset-ticks
    end
    
    to go
      ask links [ set attribute attribute * 0.5 ]
      tick
    end
    

    It just creates three turtles with links between them, sets the attribute of the link to a random number and repeatedly halves that number as the model ticks.

    To generate the csv that we will embed into our BehaviorSpace results, we write the following reporter:

    to-report link-attributes-csv
      report csv:to-string
        fput ["who1" "who2" "attribute" ] 
        [ (list [ who ] of end1 [ who ] of end2 attribute) ] of links
    end
    

    If you try it out in the command center after running setup, it will output something like this:

    observer> setup
    observer> print link-attributes-csv
    who1,who2,attribute
    0,1,0.9409784968740699
    1,2,0.9079884204004846
    0,2,0.9070292656950991
    

    As you can see, we have a neat little csv table, where each row represents a particular link, identified by the who number of the turtles it connects.

    Since this reporter reports a string (and it's ok for this string to contain line breaks), we can use it directly in a BehaviorSpace experiment:

    example experiment

    Running this experiment (with "table output") gives the following output file:

    "BehaviorSpace results (NetLogo 6.1.1)"
    "link-attributes-example.nlogo"
    "experiment"
    "10/16/2019 11:00:12:495 +0100"
    "min-pxcor","max-pxcor","min-pycor","max-pycor"
    "-16","16","-16","16"
    "[run number]","[step]","link-attributes"
    "1","0","who1,who2,attribute
    1,2,0.15670083797389645
    0,2,0.40055350697928993
    0,1,0.34892645306446335"
    "2","0","who1,who2,attribute
    0,1,0.2831244347856665
    1,2,0.27721328746715357
    0,2,0.5221352362751627"
    "2","1","who1,who2,attribute
    0,1,0.14156221739283326
    0,2,0.26106761813758134
    1,2,0.13860664373357678"
    "1","1","who1,who2,attribute
    0,2,0.20027675348964497
    1,2,0.07835041898694822
    0,1,0.17446322653223167"
    "1","2","who1,who2,attribute
    1,2,0.03917520949347411
    0,2,0.10013837674482248
    0,1,0.08723161326611584"
    "2","2","who1,who2,attribute
    1,2,0.06930332186678839
    0,1,0.07078110869641663
    0,2,0.13053380906879067"
    

    It looks at bit weird with all the line breaks, but your data analysis tools should be able to deal with that. Here is how to handle this using R and the Tidyverse:

    library(tidyverse)
    df <-
      read_csv("experiment-table.csv", skip = 6) %>%
      mutate(`link-attributes` = map(`link-attributes`, read_csv)) %>%
      unnest()
    

    The purrr::map and tidyr::unnest functions are the key ones. I won't explain them here, but its worth looking them up and familiarizing yourself with them.

    Our final result looks like this:

    # A tibble: 18 x 5
       `[run number]` `[step]`  who1  who2 attribute
                <dbl>    <dbl> <dbl> <dbl>     <dbl>
     1              1        0     1     2    0.157 
     2              1        0     0     2    0.401 
     3              1        0     0     1    0.349 
     4              2        0     0     1    0.283 
     5              2        0     1     2    0.277 
     6              2        0     0     2    0.522 
     7              2        1     0     1    0.142 
     8              2        1     0     2    0.261 
     9              2        1     1     2    0.139 
    10              1        1     0     2    0.200 
    11              1        1     1     2    0.0784
    12              1        1     0     1    0.174 
    13              1        2     1     2    0.0392
    14              1        2     0     2    0.100 
    15              1        2     0     1    0.0872
    16              2        2     1     2    0.0693
    17              2        2     0     1    0.0708
    18              2        2     0     2    0.131 
    

    I hope this helps.