0

我有一个这样的列表列表:

list = [[year1-month1,int1,float1],[year1-month1,int2,float2],[year1-month2,int3,float3]....

我需要定义一个通过它返回结果的函数,如下所示:

newList = [[((int1*float1)+(int2*float2))/(float1+float2),year-month1],...

我的问题是,超过 2000 个子列表的第一项是年月格式的日期,其余的是天数,我需要获取月平均值。我尝试了几件事,但无法让它工作。我会很感激一些建议。

我尝试过的是:

    def avPrice(mylist):
        month=[]
        i = 0
        for i in mylist:
            if mylist[i][0] not in month:
                month = mylist[i][0],mylist[i][1]*mylist[i][2],mylist[i][2]
            else:
                month = month[0],month[1]+(mylist[i][1]*mylist[line][2]),month[2]+mylist[i][2]
                i = i + 1
            return month
        monthAvPrice.append(month)
4

3 回答 3

2

使用 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为列表。也就是说,因为vitertools.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]]
于 2012-12-17T01:35:52.603 回答
1

这就是我想出的。

def appendDateNumbers(d, item):
    def sumItem(date, integer, floating, *junk):
        if date in d:
            d[date]+=integer*floating
        else:
            d[date]=integer*floating
        return d
    return sumItem(*item)

def _averageListWith(dn, datesList):
    def averageItem(i):
        return (i, dn[i]/datesList.count(i))
    return dict(map(averageItem, dn.keys()))

def averageLst(lst):
    return _averageListWith(reduce(appendDateNumbers, lst, {}), 
                            map(lambda x: x[0], lst))

print averageLst([["12-12", 1, 1.0],["12-12", 2, 2.2],["13-1", 3, 3.3]])

averageLst() 函数应该为您提供加或减舍入误差。

于 2012-12-17T01:31:52.697 回答
0

我知道可能有更好的方法,但是您是否尝试过使用 for 循环?

def monthly_average(list):
    newList=[]
    for i in range(len(list)/2):
        avg=((list[i][1]*list[i][2])+(list[i+1][1]+list[i+1][2]))
        avg=avg/(list[i][2]+list[i+1][2])
        newList.append(avg)
        newList.append(list[i][0])
    return newList

假设您每个月都有两个子列表,那应该可以工作。如果您有更多,那么您可能必须添加一个函数来检查其“第零”索引等于某个字符串的所有子列表。例如:

newList=[]
tempList=[]
for i in list:
    if i[0]=='year1-month1':
        tempList.append(i)
while len(tempList)>1:
    tempList=monthly_average(tempList)

然后每个月重复一次,更改字符串值。

同样,它可能不是最有效的方法,但它确实有效。

于 2012-12-17T01:28:15.217 回答