【问题标题】:Python - Averaging items in a list of listsPython - 平均列表中的项目
【发布时间】:2015-06-11 09:11:17
【问题描述】:

我有一个这样的列表列表

[[name1, 10.10], [name2, 12.12], [name1, 9.90], [name3, 22.20], [name3, 7.70]]

我想在更大的列表中搜索具有相同第一个元素的各个列表,然后平均第二个元素,然后将新的平均值附加到一个新列表中,如下所示:

[[name1, 10.00], [name2, 12.12], [name3, 14.95]]

问题是我不知道如何通过列表进行搜索。我对python很陌生,有人可以帮忙吗?

【问题讨论】:

  • 为什么要删除三个元素?
  • 您希望每个名字在最终列表中只出现一次,对吗?如果是这样,您不想在最终结构中使用列表,而是需要字典。
  • 你最后的分数是7,70 or 7.70?
  • 这不是名称字符串吗?
  • 编辑:我只是提交一个答案,在 cmets 中的格式很糟糕。

标签: python list


【解决方案1】:

您可以使用字典来存储具有相应值的每个名称:

>>> from __future__ import division
>>> l=[['name1', 10.1], ['name2', 12.12], ['name1', 9.9], ['name3', 22.2], ['name3', 7.70]]
>>> d={}
>>> for i in l:
...     d.setdefault(i[0],[]).extend(i[1:])
... 
>>> d
{'name2': [12.12], 'name3': [22.2, 7.7], 'name1': [10.1, 9.9]}
>>> [[i,sum(j)/len(j)] for i,j in d.items()]
[['name2', 12.12], ['name3', 14.95], ['name1', 10.0]]

Note 如果您的子列表中有超过 1 个数字,则此答案有效!!

但是对于我在编辑之前写的这种情况,您可以这样做:

>>> from __future__ import division
>>> l=[['name1', 10.1], ['name2', 12.12], ['name1', 9.9], ['name3', 22.2], ['name3', 7.70]]
>>> d={}
>>> for i,j in l:
...     d.setdefault(i,[]).append(j)
... 
>>> d
{'name2': [12.12], 'name3': [22.2, 7.7], 'name1': [10.1, 9.9]}
>>> [[i,sum(j)/len(j)] for i,j in d.items()]
[['name2', 12.12], ['name3', 14.95], ['name1', 10.0]]

【讨论】:

  • name3 的平均值不是 17.3666。
  • @zachgates7 我以为是 OP 的错字,谢谢提醒,已修复!
  • 也不是33.066;注意问题中的平均值是14.95。问题中的7,70 是错字。
  • @zachgates7 是的,我明白了,问题是因为division,已修复!
  • 反对的选民请注意编辑!并删除您的反对票!
【解决方案2】:

您可以使用一个简单的函数来遍历项目:

def averageItems(items):
    averages = {}
    for name, data in items:
        averages.setdefault(name, []).append(data)
    for name, data in averages.items():
        averages[name] = sum(data) / len(data)
    return averages

然后使用您的列表:

data = [[name1, 10.10], [name2, 12.12], [name1, 9.90], [name3, 22.20], [name3, 7.70]]
dataAverages = averageItems(data) # {name3: 14.95, name2: 12.12, name1: 10.0}

【讨论】:

  • 您的示例不起作用。你忘了引用字符串。
  • 我根据帖子编辑了问题。该帖子没有引号,表明它们是变量。 @MauroBaraldi
  • 但是你粘贴了你在 shell 中运行的例子。当然,它在您粘贴时不起作用。
  • 不需要.keys
  • 谢谢。定义函数对我来说还不是一个强项,但我想我可以按照你的例子来构建我自己的
【解决方案3】:
  1. 使用字典的.setdefault() 方法构建一个其值为数字列表的字典。
  2. 使用内置函数 sumlen 构建一个列表来计算平均值。

使用ipython 解释器

In [1]: l = [['name1', 10.10], ['name2', 12.12], ['name1', 9.90], ['name3', 22.20], ['name3', 7.70]]
In [2]: d = {}
In [3]: for k, v in l: d[k]=d.setdefault(k,[])+[v]
In [4]: [[k,sum(d[k])/len(d[k])] for k in d]
Out[4]: [['name2', 12.12], ['name3', 14.95], ['name1', 10.0]]
In [5]: del d
In [6]: 

Kevin's comment to the OP 提示最终要求保留原始列表中标签的顺序,我建议使用 collections 模块中的 OrderedDict

In [19]: from collections import OrderedDict
In [20]: d = OrderedDict()
In [21]: for k, v in l: d[k]=d.setdefault(k,[])+[v]
In [22]: [[k,sum(d[k])/len(d[k])] for k in d]
Out[22]: [['name1', 10.0], ['name2', 12.12], ['name3', 14.95]]

【讨论】:

  • 那我的回答有什么不同呢? :)
【解决方案4】:

您可以使用collections.defaultdict 将每个名称的所有分数存储在一个列表中,然后使用statistics.mean 如果您的python >= 3.4 来计算平均值:

from collections import defaultdict
from statistics import mean

l = [['name1', 10.10], ['name2', 12.12], ['name1', 9.90], ['name3', 22.20], ['name3', 7.70]]


details = defaultdict(list)

for name, score in l:
    details[name].append(score)

如果您想保留 dict 结构,只需更新值:

for name, scores in details.items():
    details[name] = mean(scores)

print(details)
defaultdict(<class 'list'>, {'name3': 14.95, 'name1': 10.0, 'name2': 12.12})

或者使用列表推导式创建一个列表:

print([[name ,mean(scores)] for name,scores in details.items()])
[['name1', 10.0], ['name3', 14.95], ['name2', 12.12]]

显然不使用 mean 你可以自己简单地计算:

print([[name , sum(scores)/len(scores)] for name,scores in details.items()])

如果订单很重要,请使用collections.OrderedDict

from collections import OrderedDict
details = OrderedDict()

for name, score in l:
    details.setdefault(name,[])
    details[name].append(score)

print([[name , sum(scores)/len(scores)] for name,scores in details.items()])

【讨论】:

  • 如果您已超过 3.x,则使用 mean 非常棒。如果没有,你将不得不手动求和和除(恐怖~)
  • @ap.我已经说过你需要 python 3.4 或更高版本。这实际上有效并给出了正确的结果,我相信 OP 可以在不使用平均值的情况下找出如何平均。
  • 你说得对,一开始我只是错过了(没看你的序言)。不是在抨击,只是指出来。
【解决方案5】:
from collections import defaultdict
from operator import add

d = defaultdict(list)
pairs = [[name1, 10.10], [name2, 12.12], [name1, 9.90], [name3, 22.20], [name3, 7.70]]

for name, val in pairs: 
    d[name].append(val)
print [(name, reduce(add, vals)/len(vals)) for name, vals in d.items()]

我认为这应该可行,而且它也相当干净。我们创建一个 defaultdict 并将每个名称的每个值附加到一个列表中,然后通过添加减少这些值,然后除以长度以获得平均值。

【讨论】:

  • 你的最后一行应该是print([[name, reduce(add, vals)/len(vals)] for name, vals in d.items()])
  • 感谢您提及.items() 部分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-14
  • 2015-06-06
  • 2015-01-20
  • 2022-01-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多