itertools.groupby() を使用して 1 か月のエントリをグループ化し、reduce() を使用して数値を合計します。例えば:
import itertools
ddat= [['2012-01', 1, 5.4], ['2012-01', 2, 8.1], ['2012-01', 3, 10.8],
['2012-01', 4, 13.5], ['2012-02', 1, 8.1], ['2012-02', 2,10.8],
['2012-02', 3, 13.5], ['2012-02', 4, 16.2], ['2012-03', 1, 10.8],
['2012-03', 2, 13.5], ['2012-03', 3, 16.2], ['2012-03', 4, 18.9],
['2012-04', 1, 13.5], ['2012-04', 2, 16.2], ['2012-04', 3,18.9]]
[[w[0], reduce(lambda x, y: x+y[1]*y[2], list(w[1]), 0)] for w in itertools.groupby(ddat, key=lambda x:x[0])]
生産する
[['2012-01', 108.0],
['2012-02', 135.0],
['2012-03', 162.0],
['2012-04', 102.6]]
編集:上記は、目的の値の分子のみを取得します。以下に示すコードは、分子と分母の両方を計算します。デモ コードとして、値とその比率の両方を含むリストを生成します。
for
次のコードの明らかに余分なものに注意してください。(つまり
... for w,v in [[w, list(v)] for w,v in itertools ...
、コードの 3 行目の部分です。) の余分な層はfor
、 iterable のコピーをv
リストとして作成するために使用されます。つまり、v
itertools.groupby() によって返されるのは実際のリストではなく反復可能であるnumer_sum(v)
ためv
、尽きdenom_sum(v)
てしまい、値が 0 になります。もう 1 つの方法は、 itertools.tee; を使用することです。しかし、別の質問への回答は、list
アプローチがより高速である可能性があると述べています。numer_sum
3 つ目の可能性は、 andを組み合わせdenom_sum
てタプルを返す単一の関数にしfor
、比率を計算するためにアウターを追加することです。
def numer_sum(w): return reduce(lambda x,y: x+y[1]*y[2], w, 0)
def denom_sum(w): return reduce(lambda x,y: x+y[2], w, 0)
[[w, round(denom_sum(v),3), numer_sum(v), numer_sum(v)/denom_sum(v)] for w,v in [[w, list(v)] for w,v in itertools.groupby(ddat, key=lambda x:x[0])]]
生産する
[['2012-01', 37.8, 108.0, 2.857142857142857],
['2012-02', 48.6, 135.0, 2.777777777777778],
['2012-03', 59.4, 162.0, 2.7272727272727275],
['2012-04', 48.6, 102.6, 2.111111111111111]]