使用 itertools.groupby() 将一个月的条目组合在一起,并使用 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 ...
第三行代码中的部分。)额外的层for
用于将可迭代的副本制作v
为列表。也就是说,因为v
itertools.groupby() 返回的是一个可迭代的而不是一个实际的列表,所以numer_sum(v)
会用尽v
,所以denom_sum(v)
会得到一个值 0。另一种方法是使用 itertools.tee;但另一个问题的答案说这种list
方法可能更快。第三种可能性是将numer_sum
和组合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]]