1 次元リスト内のアイテムの平均を見つける必要があります: 例: L = [123,678,234,256,789,-----] 最初に、リストの最後のアイテムから始まる移動平均を取得する必要があります。したがって、結果を提供します。次のようにリストします: reslist= [416,489.25,426.33,522.5,789---]. Plzは、これを行うためのPythonで簡単なコードを提案できます..
2 に答える
したがって、各 indexについて、までi
の値の平均が必要ですよね?L[i]
L[-1]
まず、簡単なaverage
関数を書きましょう。
def average(values):
return sum(values) / len(values)
これで、説明をコードに変換できます。
running_averages = [average(L[i:]) for i in range(len(L))]
また、特定されていない方法で丸めたいようです (489.25 は 489 に丸められますが、522.5 は 522.5 のままです)。ルールを説明できれば、それを実装する方法を示すことができますが、あなたの例からルールを推測することはできません.
もちろん、これは L が長い場合はあまり効率的ではありませんlen(L)**2 / 2
。加算を行うからです。だけでそれを行う方法はありlen(L)
ますか? 確かに、それはもう少し複雑です。例えば:
partial_sums = itertools.accumulate(reversed(L))
averages = [value/(i+1) for i, value in enumerate(partial_sums)]
averages.reverse()
最初と最後のステップは簡単です。最初と最後でリストを逆にするだけです。しかし、残りはどうですか?
まず、accumulate
任意の iterable を取得し、合計を累積したイテレータを返します。i[0]
したがって、 、 then i[0] + i[1]
、 thenなどが得られますi[0] + i[1] + i[2]
。ただし、最後の部分和が記憶されているため、各ステップでは加算が 1 回だけ行われます。言い換えれば、それはあなた0 + i[0]
に 、その後result[0] + i[1]
、そしてを与えていますresult[1] + i[2]
。それがどのように機能するかを確認したい場合 (または を持たない古いバージョンの Python を使用している場合accumulate
) は、リンクされたドキュメントに自分でビルドする方法が示されています。
次に、各部分合計をインデックス (+ 1、Python のインデックスは 0 から始まるため) で除算して、移動平均を取得します。リストの理解は明らかです。関数がわからない場合はenumerate
、それが唯一の賢いビットです。
それが唯一の方法ではありません。、または明示的なループを使用functools.reduce
したり、アキュムレータを渡すことによって末尾再帰関数を作成したり、単純な再帰関数を作成したりすることもできます。または… できるだけ多くの関数を書くことを試みるのは良い練習になるかもしれません。それを行う明白な方法は 1 つしかないかもしれませんが、いくつか試してみないと、どれが明白な方法であるかが明らかでない場合があります。:)
これを行う別の方法は、numpy を使用することです。rogaos は単純すぎる回答を削除しましたが、それは始まりです。
まず、簡単な部分: リストを逆にして、numpy 配列に詰め込みます。
a = np.array(reversed(L))
ここでの秘訣は、ベクトル化された実行中の合計を記述することです。さて、numpy には が付属しておりconvolve
、N 個の実行を畳み込むと、N+M-1 ウィンドウの合計が得られます。では、ウィンドウが配列全体と同じ幅の場合はどうなるでしょうか? 必要な長さのほぼ 2 倍の長さのウィンドウ合計が得られます。ここで、最初の len(L) 値は実行中の合計です。そう:
running_sums = np.convolve(a, np.ones(len(L)))[:len(L)]
次に、itertools バージョンと同様に、インデックスで除算します。
running_means = running_sums / np.arange(1, len(L)+1)
そして今、それを逆にしてリストに戻します:
reslist = list(reversed(running_means))
もちろん、実生活では、 numpy 配列も必要L
にreslist
なるため、さらに単純になります。
とにかく、numpy を使用することの利点は、一部の操作がより単純であり (リスト内包表記を記述する代わりに、ある配列を別の配列で割った方法に注意してください)、通常は約 10 倍高速です (すべてのループと演算は C で行われます)。 、または場合によっては Python の代わりに C++ または Fortran)。欠点は、各ループを適切な数学的操作に変換する方法を理解しなければならないことです。(何をするかわからない場合convolve
は、ここでそれを使用することを決して考えなかったでしょう.)
再帰を使用するソリューションは次のとおりです。
def runningMean(seq, n=0, total=0):
if not seq:
return []
total = total+seq[-1]
return runningMean(seq[:-1], n=n+1, total=total) + [total/float(n+1)]
デモ
print(runningMean([123,678,234,256,789]))
出力:
[416.0, 489.25, 426.3333333333333, 522.5, 789.0]