How to calculate weighted average of non-zero values?

huangapple go评论110阅读模式
英文:

How to calculate weighted average of non-zero values?

问题

我是新手学习Go语言,我正在做以下操作:

我有一个切片:

valueList := []int16{500, 400, 0, 300}

还有一个权重切片:

weightList := []float64{0.1, 0.2, 0.3, 0.4}

现在我想要做的是:

res := make([]float64, 4)
for i, value := range valueList {
    res[i] = float64(value) * weightList[i]
}

但是正如你所看到的,我在valueList中得到了一个0,现在如果值不是0,我想要将权重平均分配给其他值,所以在这个例子中,应该是:

500 * (0.1 + 0.3/3) + 400 * (0.2 + 0.3/3) + 300 * (0.4 + 0.3/3)

如果另一个0出现,再次平均分配权重。

我该如何简单地实现这个功能?

英文:

I am new to Go, I am doing the following:

I have a slice:

valueList := []int16{500, 400, 0, 300}

and a weight slice:

weightList := []float64{0.1, 0.2, 0.3, 0.4}

Now I want to do this:

res := make([]float64, 4)
for i, value := range valueList {
    res[i] = float64(value) * weightList[i]
}

But as you can see, I get a 0 in valueList, now I want to average the weight to the others if value is not 0, so in this example, it should be:

500 * (0.1 + 0.3/3) + 400 * (0.2 + 0.3/3) + 300 * (0.4 + 0.3/3)

If another 0 shows up, average the weight again.

How can I do this simply?

答案1

得分: 3

你可以在迭代非零值时计算它们的总权重,并在最后通过总权重进行除法运算:

vs := []int{500, 400, 0, 300}
ws := []float64{0.1, 0.2, 0.3, 0.4}

sumWeight, avg := 0.0, 0.0
for i, v := range vs {
    if v == 0 {
        continue
    }
    sumWeight += ws[i]
    avg += float64(v) * ws[i]
}
avg /= sumWeight

fmt.Println("平均值:", avg)

输出结果(在Go Playground上尝试):

平均值:357.1428571428571

注意:

此解决方案不要求权重总和为1.0,也不要求在0..1的范围内(但不能为负)。

注意2:

如果输入切片为空(长度为0或所有值都为0),或者非零值的总权重为0.0,由于除以sumWeight(即0.0),结果将为NaN。你可能想检查这种情况并采取其他措施:

if sumWeight > 0.0 {
    avg /= sumWeight
}
英文:

You can calculate the sum weight of non-zero values while iterating over them, and do the division by the sum weight at the end:

vs := []int{500, 400, 0, 300}
ws := []float64{0.1, 0.2, 0.3, 0.4}

sumWeight, avg := 0.0, 0.0
for i, v := range vs {
	if v == 0 {
		continue
	}
	sumWeight += ws[i]
	avg += float64(v) * ws[i]
}
avg /= sumWeight

fmt.Println("Average:", avg)

Output (try it on the Go Playground):

Average: 357.1428571428571

Note:

This solution does not require weights to sum up to 1.0 neither to be in the range of 0..1 (but they can't be negative).

Note #2:

If the input slices are empty (either by having len == 0 or all values being 0) or sumWeight of non-zero values is 0.0, the result will be NaN due to dividing by sumWeight which is 0.0. You might want to check this case and do something else:

if sumWeight > 0.0 {
	avg /= sumWeight
}

huangapple
  • 本文由 发表于 2015年5月27日 19:11:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/30480782.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定