在 NetLogo 中嵌套 foreach

Nested foreach in NetLogo

我正在尝试计算一组数字的基尼系数。基尼系数是平均绝对差值的一半。也就是说,对于列表中每一对可能的数字,我需要取它们的绝对差并将这些差加在一起(以及其他一些东西)。这是我的代码

to-report calc-Gini [list-Values]
  let sumdiff 0
  foreach list-Values
  [ foreach list-Values
    [ set sumdiff sumdiff + abs ( ?1 - ?2 )
    ]
  ]
  report 0.5 * sumdiff / (mean list-Values * (length list-Values) ^ 2)
end

当我测试它时(例如 show calc-Gini (list 1 2 3)),我在第二个 foreach 上收到错误 "task expected 2 inputs, but only got 1"。

我认为问题在于 NetLogo 希望 运行 同时通过 foreach 循环。因此,如果列表长度为 N,则它仅创建 N 对(即 list1 中的第一项和 list2 中的第一项,然后是每个列表中的第二项等),这就是等长列表的要求所在。但是我需要它来处理通过交叉列表获得的 N^2 对。

如何让嵌套的 foreach 做我想做的事 and/or 其他一些原语更合适吗?

我无法解决您的嵌套 foreach 方法,但这可能是您进行计算的另一种方法:

如果您使用有序数据,则可以使用此等式计算基尼系数(给定向量 $y$,其中 $y_i$、$i=1,...,n$)

$$ G(y) = \frac{1}{n} (n + 1 - 2 * \frac{ \sum_{i=1}^{n} (n + 1 - i) y_{ i} }{ \sum_{i=1}^{n} y_i} $$

下面的报告者应该在 NetLogo 中传递结果:

to-report calc-Gini [list-Values]
  let values sort list-Values ; making sure values are in a non-decreasing order
  let n length values
  let i 1
  let numerator []
  foreach values 
  [ set numerator lput ( (n + 1 - i) * ? ) numerator
    set i i + 1
  ]
  report 1 / n * ( n + 1 - 2 * (sum(numerator) / sum(values)) )
end

NetLogo 没有将 ?1?2 绑定到外部和内部任务的机制。当它在您的代码中看到 ?1?2 时,它预计 both 输入将来自内部任务。由于内部 foreach 只提供一个输入,NetLogo 抱怨道。

您可以通过简单地将外部 foreach 的输入分配给局部变量来解决该问题:

to-report calc-Gini [list-Values]
  let sumdiff 0
  foreach list-Values
  [ let v ?
    foreach list-Values
    [ set sumdiff sumdiff + abs ( v - ? )
    ]
  ]
  report 0.5 * sumdiff / (mean list-Values * (length list-Values) ^ 2)
end

话虽这么说,但这是另一种实现方式:

to-report calc-gini [ xs ]
  report 0.5 * sum map [ sum-diff ? xs ] xs / (mean xs * (length xs) ^ 2)
end

to-report sum-diff [ x xs ]
  report sum map [ abs (x - ?) ] xs
end