首页 > 解决方案 > 基于键名的元组平均列表?

问题描述

modifiedL = [('10-1984', 2.8), ('10-1984', 2.8), ('10-1984', 2.85), ('10-1984', 2.82), ('10-1984', 2.78), ('10-1984', 2.75), ('09-1984', 2.82), ('09-1984', 2.9), ('09-1984', 2.9), ('09-1984', 2.94), ('09-1984', 2.99), ('09-1984', 3.02), ('09-1984', 3.05), ('09-1984', 3.04), ('09-1984', 3.11), ('09-1984', 3.22), ('09-1984', 3.13), ('09-1984', 3.09), ('09-1984', 2.94), ('09-1984', 3.02), ('09-1984', 2.97), ('09-1984', 2.98)]

avg={}

for date, value in modifiedL:
    avg.setdefault(date, []).append(value)

for key, value in avg.items():
    avg[key] = sum(value)/float(len(value))

第一次循环后:

avg = {'10-1984': [2.8, 2.81, 2.78, 2.77, 2.84, 2.95, 2.92, 2.85, 2.88, 2.88, 2.8, 2.68, 2.7, 2.56, 2.67, 2.68, 2.77, 2.8, 2.8, 2.85, 2.82, 2.78, 2.75], '09-1984': [2.82, 2.9, 2.9, 2.94, 2.99, 3.02, 3.05, 3.04, 3.11, 3.22, 3.13, 3.09, 2.94, 3.02, 2.97, 2.98]}

第二次循环后:

avg= {'10-1984': average, '09-1984': average}

有没有办法简化代码或在一行中执行此操作?

标签: python-3.xdictionary

解决方案


你的代码很好。您可以替换其中的某些部分(例如使用defaultdictor statistics.mean),但仍需要 2 个循环。没有实际的理由让每个代码都成为单行代码,最好只创建一个具有好名称的函数。

但是,有一些选项可以使其成为单线。您可以使用itertools.groupby(请注意,这会将算法复杂度增加到 O(N log N) :

In [11]: from itertools import groupby

In [12]: from operator import itemgetter

In [13]: from statistics import mean

In [14]: {k: mean(map(itemgetter(1), v)) for k, v in groupby(sorted(modifiedL, key=itemgetter(0)), key=itemgetter(0))}
Out[14]: {'09-1984': 3.0075, '10-1984': 2.8}

您可以编写您的 groupby 版本,它不需要对序列进行排序以将复杂性降低回 O(N)(请参阅此答案以获取示例)

或者,如果您在项目中使用 pandas,您可以将列表转换为 DataFrame:

In [29]: import pandas as pd

In [30]: df = pd.DataFrame(modifiedL)

In [31]: df.groupby(0).mean()
Out[31]:
              1
0
09-1984  3.0075
10-1984  2.8000

推荐阅读