0

我有一个应该执行以下操作的函数:获取列表列表和数字权重列表。然后,取列表列表中每个底层项的加权平均值,权重列表中的第一项用于加权第一个事物列表,权重列表中的第二项用于加权第二个列表,等等。它就像一个函数,只取列表中项目的加权平均值,但项目被分组,以便将特定权重应用于每个组。如果很多东西的重量相同,这很有用。这是代码:

def getAverage(x,wts=[0.1,0.3,0.6]):
    """Get weighted average of partitioned list."""
    xsum = 0
    i = 0
    for item in x:
        xsum += reduce(lambda x,y:x+y,item)*wts[i]
        i += 1
    return xsum/reduce(lambda x,y:x+y,wts)

但是,当我尝试编译时,该行出现以下错误:

TypeError: unsupported operand type(s) for +=: 'int' and 'list'

什么?为什么?为什么这个乘法会返回一个列表?这是没有意义的。reduce()返回一个数字(准确地说是整数),其中的元素wts是浮点数。怎么不允许加到xsum?是我用错lambda了还是怎么的?

4

1 回答 1

4

您的函数主要是合理的(尽管我认为它要么命名错误,要么您也想除以最后的项目数 - 否则它不是平均值),所以您必须传入不正确的参数。最有可能的是,您的第二个参数实际上是列表列表,而不是整数列表。

这就是说,我们可以改进功能。这里有几个问题。首先,当内置可以更有效地完成这项工作时reduce()您正在使用汇总项目。sum()

接下来,循环计数使用i- 这是一个不好的做法,相反,我们应该使用内置enumerate(). 但是,这里我们使用它同时循环两个列表,在 Python 中,最好使用内置zip.

随着结果的积累,我们可以将整个事情变成一个生成器表达式并对其进行求和。这意味着我们最终可以通过一种简单的方式来执行此操作:

def weighted_average(items, weights):
    total = sum(sum(item)*weight for item, weight in zip(items, weights))
    return total/sum(weights)

我还省略了权重的默认值 - 除非默认值是特定于域的,否则我建议这里没有好的默认值,因为它取决于items. 一个好的默认值的唯一可能是假设相等的权重。例如:

def weighted_average(items, weights=None):
    if not weights:
        weights = [1]*len(items)
    total = sum(sum(item)*weight for item, weight in zip_longest(items, weights))
    return total/sum(weights)
于 2013-01-12T18:22:37.723 回答