0

次のことを行うはずの関数があります。リストのリストと数値の重みのリストを取り込みます。次に、リストのリストの最下位レベルのすべての項目の加重平均を取り、重みのリストの最初の項目を使用して最初の項目のリストを重み付けし、重みのリストの 2 番目の項目を重み付けに使用します。 2番目のリストなど。これは、リスト内のアイテムの加重平均を取る関数に似ていますが、アイテムはグループ化されているため、特定の重みが各グループに適用されます。これは、同じ重さのものがたくさんある場合に便利です。コードは次のとおりです。

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は float です。xsum に追加できないのはなぜですか? 私はlambda何かを悪用しましたか?

4

1 に答える 1

4

あなたの関数は主に健全です(名前が間違っているか、最後にアイテムの数で割りたいと思いますが、そうでなければ平均ではありません)、間違った引数を渡す必要があります。最も可能性が高いのは、2番目の引数が実際には整数のリストではなく、リストのリストであるということです。

そうは言っても、機能を改善することができます。ここにはいくつかの問題があります。まず、ビルトインがこの仕事をより効果的に行うことができるときにreduce()アイテムを合計するために使用しています。sum()

次に、ループカウントを使用しますi-これは悪い習慣ですが、代わりに、組み込みのを使用するenumerate()必要があります。ただし、ここでは2つのリストを同時にループするために使用しています。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 に答える