排序列表中的多个条目的平均值

时间:2016-02-26 00:27:49

标签: python list

我有一个排序的二维列表,其中第一列中的特定值可以多次出现,但在第二列中有不同的对应值。

示例:

1   10
2   20
3   30
3   35
4   40
5   45
5   50
5   55
6   60

我想对这些多个条目进行平均,以便我的最终列表看起来像

1   10
2   20
3   32.5
4   40
5   50
6   60

一个问题是,您不知道值发生了多少次。到目前为止我的代码看起来像

for i in range(len(list)):
    print i
    if i+1 < len(list):
        if list[i][0] == list[i+1][0]:
            j = 0
            sum = 0
            while list[i][0] == list[i+j][0]:     #this while loop is there to account for the unknown number of multiple values
                sum += list[i+j][1]
                j += 1
            avg = sum / j
            #print avg
            #i+=j                                 # here I try to skip the next j steps in the for loop, but it doesn't work
            #final[i].append(i)
            #final[i].append(avg)                 # How do I append a tuple [i, avg] to the final list?
        else:
            final.append(list[i])
    else:
        final.append(list[i])
print final

我的问题是:

  • 如何正确计算多个条目并且不计算在内 他们两次使用for循环?
  • 如何将元组[i,avg]附加到最终列表?

4 个答案:

答案 0 :(得分:2)

以下代码正在使用groupby中的itertools

lst = [[1, 10],
       [2, 20],
       [3, 30],
       [3, 35],
       [4, 40],
       [5, 45],
       [5, 50],
       [5, 55],
       [6, 60],
       ]
from itertools import groupby

avglst = []
for grpname, grpvalues in groupby(lst, lambda itm: itm[0]):
    values = [itm[1] for itm in grpvalues]
    avgval = float(sum(values)) / len(values)
    avglst.append([grpname, avgval])
print(avglst)

运行时:

$ python avglist.py                                                                    (env: stack)
python[[1, 10.0], [2, 20.0], [3, 32.5], [4, 40.0], [5, 50.0], [6, 60.0]]

它提供了您要求的结果。

说明:

groupby可迭代(列表)和一个函数,它计算名为key的值,即一个值, 用于创建组。在我们的例子中,我们将根据列表项中的第一个元素进行分组。

注意,groupby每次键值更改时都会创建组,因此请确保输入列表是 排序,否则你得到的组数超出预期。

groupby返回元组(grpname, groupvalues),其中grpname是给定的关键值 group,groupvalues是该组中所有项目的迭代器。小心,事实并非如此 列表,要从中获取列表,某些内容(如调用list(grpvalues))必须遍历值。 在我们的例子中,我们使用列表理解来迭代,每个列表元素中只选择第二项。

虽然python中的迭代器,生成器和类似结构起初可能看起来太复杂了, 他们目前服务非常好,必须处理非常大的列表和迭代。在这样的 例如,Python迭代器只在内存中保存当前项目,因此可以管理非常大或甚至 无休止的迭代。

答案 1 :(得分:1)

您可以使用字典计算左列中每个值出现的次数吗?还有一个单独的字典来映射与每个左边条目相关的元素总和。然后使用一个最终的for循环,将总和除以计数。

from collections import defaultdict
someList = [(1,10), (2,20), (3,30), (4,40), (5,45), (5,50), (5,55)]
count_dict = defaultdict(lambda:0)
sum_dict = defaultdict(lambda:0.0)
for left_val, right_val in someList:
    count_dict[left_val] += 1
    sum_dict[left_val] += right_val

for left_val in sorted(count_dict):
    print left_val, sum_dict[left_val]/count_dict[left_val]

输出

1 10.0
2 20.0
3 30.0
4 40.0
5 50.0

答案 2 :(得分:1)

首先,我们需要将列组合在一起。我们将使用字典,其中键是左列,值是该键的值列表。然后,我们可以进行简单的计算以获得平均值。

from  collections import defaultdict

data = [
    (1, 10),
    (2, 20),
    (3, 30),
    (3, 35),
    (4, 40),
    (5, 45),
    (5, 50),
    (5, 55),
    (6, 60)
]

# Organize the data into a dict
d = defaultdict(list)
for key, value in data:
    d[key].append(value)

# Calculate the averages
averages = dict()
for key in d:
    averages[key] = sum(d[key]) / float(len(d[key]))

# Use the averages
print(averages)

输出:

{1: 10.0, 2: 20.0, 3: 32.5, 4: 40.0, 5: 50.0, 6: 60.0}

答案 3 :(得分:1)

以下是CounterOrderedDict组合的方法:

from __future__ import division  # Python 2
from collections import Counter, OrderedDict
counts, sums = OrderedDict(), Counter()
for left, right in [(1,10), (2,20), (3,30), (4,40), (5,45), (5,50), (5,55)]:
    counts[left] = counts.get(left, 0) + 1
    sums[left] += right

result = [(key, sums[key]/counts[key]) for key in counts]