NetLogo - 使用 BehaviorSpace 获取所有海龟位置作为每次重复的结果

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

我正在使用 BehaviorSpace 运行 使用不同参数的模型数百次。但是我需要知道所有海龟的位置,而不仅仅是海龟的数量。如何使用 BehaviorSpace 实现它?

目前,我通过以下代码将结果输出到csv文件中:

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

但所有结果都弹出到同一个 csv 文件中,所以我无法分辨每个 运行ning 的情况。

Seth 关于在 csv 输出的文件名中加入 behaviorspace-run-number 的建议是一种选择。它允许您将该文件与主 BehaviorSpace 输出文件中的摘要数据相关联。

另一种选择是在您的行为 space 实验定义中将报告者列为 "measures"。例如,在您的情况下:

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

然后您可以用您最喜欢的数据分析语言解析结果列表 "manually"。我之前在 Julia 中为此使用了以下函数:

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

我相信您可以轻松地用 Python 或 R 或​​您使用的任何语言编写一些等效代码。

在上面的示例中,我为海龟的 xcorycor 输出了单独的列表。您也可以输出单个 "list of lists",但解析会比较棘手。


编辑:如何使用 csv 扩展和 R

来做到这一点

巧合的是,今天我不得不为另一个项目做类似的事情,我意识到 csv extension 和 R 的组合可以使这变得非常容易。

大致思路如下:

  • 在 NetLogo 中,使用 csv:to-string 将列表数据编码为字符串,然后将该字符串直接写入 BehaviorSpace 输出。

  • 在 R 中,使用 purrr::map and readr::read_csv, followed by tidyr::unnest,将所有内容解压到一个整洁的 "one observation per row" 数据帧中。

换句话说:我们喜欢 CSV,所以我们将 CSV 放在 CSV 中,这样我们就可以边解析边解析。

这是一个完整的例子。假设我们有以下 NetLogo 模型:

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

然后我们使用我们的 positions 报告器作为输出来定义以下微型行为空间实验,只有两次重复和两次时间限制:

处理此问题的 R 代码非常简单:

library(tidyverse)

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

这会产生以下数据框,一切都很整洁:

> 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 

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)