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