从 csv 文件创建代理时使用 to-reports

Using to-reports while creating agents from a csv file

我的问题有点长。如果您能阅读全部内容,我将不胜感激,如果您提出任何建议,我将不胜感激。

我有 2 位海龟消费者的数据,他们对笔记本电脑的功能进行了评级。笔记本电脑有两种特性:屏幕尺寸和电池寿命。每个都有一些级别。例如电池寿命有5小时、12小时、24小时、30小时。数据存储在 csv 文件中。

   12 13.5 14 15 5 12 24 30
1  1   2    1  3 2  2  4  5
2  4   3    1  2  1 1  2  3

我想求和 2 级特征的比率。例如对于消费者 1 和 2,什么是:

13.5的屏幕尺寸总和速率+24的电池寿命速率

由于 13.5 和 24 稍后可能会更改,并且我想知道例如 14 的大小和 5 的电池寿命的比率之和,我使用 "to-reports" 定义了两个函数。此外,例如值“12”在 header 行中出现两次,代表尺寸和电池寿命,我制作了 csv 文件的 2 个子集,一个用于屏幕尺寸,另一个用于电池。

   12 13.5 14 15 
1  1   2    1  3 
2  4   3    1  2  

   5 12 24 30
1  2  2  4  5
2  1 1  2  3

首先在主程序中,读取csv文件,每行分配一个海龟,期望有两个消费者。

to setup
  ca
  reset-ticks
  file-close-all
  file-open "turtle_details.csv"
 let headerrow csv:from-row file-read-line
 set Sc 13.5   ; at the beginning I want the rate of this screen size
 set Bat 24
   while [ not file-at-end? ] [
    let data csv:from-row file-read-line
      create-consumers 1 [
         set shape "person"
         set k k + 1
       print  obtain-Sc (Sc) + obtain-Bat (Bat)
      ]
   ]
  file-close-all
end

我假设,首先读取第一行并生成消费者。现在它去 to-report 找到 obtain-Screen(13.5) 是 2,但我认为下次调用 obrain_Screen 时,csv 再次打开并且光标仍然在开头,但我希望它读取第二行。为了扩展它,我可能需要它越走越远。为了解决这个问题,我定义了一个计数器 k,例如第一次检查这个条件时:idx = 0 < k =1 所以第一行被读取。然后 idx = idx + 1 ,所以什么都不做。

to-report obtain-Screen[Sc]
  file-close-all ; close all open files

  file-open  "turtle_detailsSc.csv" 
  let headings csv:from-row file-read-line
  ifelse  is-number? position Sc headings
    [
      while [idx < k ]
      [ set fdata csv:from-row file-read-line
        set idx idx + 1
      ]
      report item position Sc headings fdata
]
[report 0.000000009]

Bat 的类似内容。但它不起作用并且有错误。有什么改进 to-report 的想法吗? 谢谢

编辑

考虑数据集是这样的:

   size12  size13.5  size14  size15  Battery5  Battery12 Battery24 Battery30 
1  1        *2*         1      3        2         2           *4*       5
2  4        3           3      2        1          1           2        3

我现在可以访问数据集,并为每个消费者找到他们对购买的笔记本电脑的评价。例如,消费者 1 的笔记本电脑尺寸为 13.5,电池寿命为 24。

Consumer 1 evaluation of size 13.5 = 2
Consumer 1 evaluation of battery 24 = 4
Overall evaluation of laptop = 2 + 4 = 6

我定义了一个过程 "Find Eval",当我需要了解不同消费者的评价时,它使我能够访问数据集并找到值。

再解释一下table中的数据,消费者有一台笔记本电脑,所以可以很好地评价它,但对于其他功能,比如他如何评价屏幕尺寸为15的笔记本电脑,他可能有他填写了 table.

我想在 20 年内留住这 2 位消费者并监控他们对笔记本电脑功能的态度。在第 2 年,消费者 1 可能更新了他的系统,所以现在他的电池寿命是 30。这次我需要做的是访问数据集并计算

Consumer 1 evaluation of size 13.5 = 2

加上

Consumer 1 evaluation of battery 30 = 5



  Overall evaluation of laptop = 2 + 5 = 7

这一次,我需要去寻找电池30的价值。 我认为当我重复我的代码 20 年时,每次我想使用数据集时都会重复 create-consumer,因此每年不会保留 2 个消费者,而是会创建一些新的消费者和以前的消费者将被完全取代。

问题是我如何才能创建消费者一次,但可以多次访问数据集中的任何数据点?

非常感谢,

回应您的评论 - 明白了,我认为可能是这样。我将介绍一种可能适合或不适合您的替代方法,但这可能是我解决这个问题的方法。主要区别在于我会将屏幕和电池额定值列表存储在一个 turtle 变量中,这样您就可以在事后轻松访问它们,而无需跟踪计数器。给定这些变量声明:

extensions [ csv ]

globals [ screen-headings battery-headings]

turtles-own [ 
  turtle-screen-list 
  turtle-battery-list
  turtle-screen-eval
  turtle-bat-eval
  turtle-sum-eval
  turtle-row-number
]

我会将 csv 文件的标题拆分为 screen-headingsbattery-headings 全局变量。

然后,我将遍历 csv 的下一行,就像您在下面所做的那样,并以类似的方式拆分这些行,但分为 turtles-own 变量 turtle-screen-listturtle-battery-list.这样,每只乌龟都知道自己对每个屏幕和电池的评级,因此您可以根据需要修改评估的屏幕或电池。

使用 screen-to-evaluatebattery-to-evaluate(或在界面上使用 Chooser)设置感兴趣的屏幕和电池,然后使用报告器(与您设置的类似) ) 检查电池的位置和感兴趣的屏幕 return 当前海龟对每个的评级 - 这将设置 turtle-screen-evalturtle-bat-eval。最后,将最后两个值相加。

to setup
  ca
  reset-ticks
  file-close-all
  file-open "turtle_details.csv"
  let headings csv:from-row file-read-line
  set screen-headings sublist headings 0 4
  set battery-headings sublist headings 4 length headings

  let screen-to-evaluate 13.5
  let battery-to-evaluate 24

  while [ not file-at-end? ] [
    let data csv:from-row file-read-line
    create-turtles 1 [
      set turtle-screen-list sublist data 0 4
      set turtle-battery-list sublist data 4 length data
      set turtle-screen-eval turtle-screen-rating screen-to-evaluate
      set turtle-bat-eval turtle-battery-rating battery-to-evaluate
      set turtle-sum-eval turtle-screen-eval + turtle-bat-eval
    ]
  ]
  file-close-all

end

to-report turtle-screen-rating [sc]
  let pos position sc screen-headings
  let turt-screen-rate-value item pos turtle-screen-list
  report turt-screen-rate-value
end

to-report turtle-battery-rating [bc]
  let pos position bc battery-headings
  let turt-bat-rate-value item pos turtle-battery-list
  report turt-bat-rate-value
end

当然,你可以根据需要压缩其中的一些。我用 4 行测试了这个设置(根据你的示例数据设计),它似乎工作正常。如果你有大量的行,它可能不会很好地工作。

编辑:

如果您最终将 screen-to-evaluatebattery-to-evaluate 替换为界面选择器(我推荐 - 它可以让您快速查看不同的值),您可以更新为新值,例如:

to update-vals
  ask turtles [
    set turtle-screen-eval turtle-screen-rating scrn
    set turtle-bat-eval turtle-battery-rating batr
    set turtle-sum-eval turtle-screen-eval + turtle-bat-eval
  ]
end

其中 scrnbatr 是选择器的名称。

或者,如果您希望它们动态更新,您可以制作一个界面监视器来报告以下报告者:

to-report update
ask turtles [
    set turtle-screen-eval turtle-screen-rating scrn
    set turtle-bat-eval turtle-battery-rating batr
    set turtle-sum-eval turtle-screen-eval + turtle-bat-eval
  ]
  report "Dynamically updating."
end

有了那个,一旦您更改 Chooser 值,海龟应该立即更新它们的 turtle-bat-evalturtle-screen-evalturtle-sum-eval。好玩!

编辑 2

如果您的 csv 包含这样的行号列:

row 12 13.5 14 15  5 12 24 30
1   1  2.0  1  3  2  2  4  5
2   4  3.0  1  2  1  1  2  3

我建议创建一个 turtle 变量来存储使用的行号。我现在包括了一个名为 turtle-row-number 的。然后,您只需要包含一行来从列表中的 first 项更新该变量,即行号,然后相应地修改您的 sublist 值,例如:

to setup-row-nums
  ca
  reset-ticks
  file-close-all
  file-open "turtle_details_2.csv"
  let headings csv:from-row file-read-line
  set screen-headings sublist headings 1 5
  set battery-headings sublist headings 5 length headings

  while [ not file-at-end? ] [
    let data csv:from-row file-read-line
    create-turtles 1 [
      set turtle-row-number first data 
      set turtle-screen-list sublist data 1 5
      set turtle-battery-list sublist data 5 length data
    ]
  ]
  update-vals
  file-close-all

end

其中update-vals如上图