在Python中计算dict列表的平均值

在Python中计算dict列表的平均值,python,Python,我有一份每日价值清单,按顺序排列成一份清单,如下所示: vals = [ {'date': '1-1-2014', 'a': 10, 'b': 33.5, 'c': 82, 'notes': 'high repeat rate'}, {'date': '2-1-2014', 'a': 5, 'b': 11.43, 'c': 182, 'notes': 'normal operations'}, {'date': '3-1-2014', 'a': 0, 'b': 0.5,

我有一份每日价值清单,按顺序排列成一份清单,如下所示:

vals = [
    {'date': '1-1-2014', 'a': 10, 'b': 33.5, 'c': 82, 'notes': 'high repeat rate'},
    {'date': '2-1-2014', 'a': 5, 'b': 11.43, 'c': 182, 'notes': 'normal operations'},
    {'date': '3-1-2014', 'a': 0, 'b': 0.5, 'c': 2, 'notes': 'high failure rate'},
    ...]
我想做的是得到一个月的平均a、b和c

有没有比这样做更好的方法:

val_points = {}
val_len = len(vals)

for day in vals:
    for p in ['a', 'b', 'c']:
        if val_points.has_key(p):
            val_points += day[p]
        else:
            val_points = day[p]

val_avg = dict([(i, val_points[i] / val_len] for p in val_points])
我还没有运行上面的代码,可能有小故障,但我希望我能让大家明白我的想法。我知道可能有更好的方法使用操作符、itertools和集合的组合

{p:sum(map(lambda x:x[p],vals))/len(vals) for p in ['a','b','c']}
输出:

{'a': 5, 'c': 88, 'b': 15.143333333333333}
{'1': {'a': 11.666666666666666, 'c': 88.66666666666667, 'b': 15.143333333333333}, 
 '2': {'a': 10.0, 'c': 2.0, 'b': 0.5}}
输出:

{'a': 5, 'c': 88, 'b': 15.143333333333333}
{'1': {'a': 11.666666666666666, 'c': 88.66666666666667, 'b': 15.143333333333333}, 
 '2': {'a': 10.0, 'c': 2.0, 'b': 0.5}}

这可能比Elisha的答案略长,但中间数据结构较少,因此速度可能更快:

KEYS = ['a', 'b', 'c']

def sum_and_count(sums_and_counts, item, key):
    prev_sum, prev_count = sums_and_counts.get(key, (0,0)) # using get to have a fall-back if there is nothing in our sums_and_counts
    return (prev_sum+item.get(key, 0), prev_count+1) # using get to have a 0 default for a non-existing key in item

sums_and_counts = reduce(lambda sc, item: {key: sum_and_count(sc, item, key) for key in KEYS}, vals, {})

averages = {k:float(total)/no for (k,(total,no)) in sums_and_counts.iteritems()}
print averages
输出

{'a': 5.0, 'c': 88.66666666666667, 'b': 15.143333333333333}

这可能比Elisha的答案略长,但中间数据结构较少,因此速度可能更快:

KEYS = ['a', 'b', 'c']

def sum_and_count(sums_and_counts, item, key):
    prev_sum, prev_count = sums_and_counts.get(key, (0,0)) # using get to have a fall-back if there is nothing in our sums_and_counts
    return (prev_sum+item.get(key, 0), prev_count+1) # using get to have a 0 default for a non-existing key in item

sums_and_counts = reduce(lambda sc, item: {key: sum_and_count(sc, item, key) for key in KEYS}, vals, {})

averages = {k:float(total)/no for (k,(total,no)) in sums_and_counts.iteritems()}
print averages
输出

{'a': 5.0, 'c': 88.66666666666667, 'b': 15.143333333333333}

如果你有多个月的数据,熊猫会让你的生活更轻松:

df = pandas.DataFrame(vals)
df.date = [pandas.datetools.parse(d, dayfirst=True) for d in df.date]
df.set_index('date', inplace=True)
means = df.resample('m', how='mean')
结果:

            a          b          c
date                               
2014-01-31  5  15.143333  88.666667

如果你有多个月的数据,熊猫会让你的生活更轻松:

df = pandas.DataFrame(vals)
df.date = [pandas.datetools.parse(d, dayfirst=True) for d in df.date]
df.set_index('date', inplace=True)
means = df.resample('m', how='mean')
结果:

            a          b          c
date                               
2014-01-31  5  15.143333  88.666667

由于您希望按月计算平均值(此处考虑“dd-mm-yyyy”中的日期格式):

输出:

{'a': 5, 'c': 88, 'b': 15.143333333333333}
{'1': {'a': 11.666666666666666, 'c': 88.66666666666667, 'b': 15.143333333333333}, 
 '2': {'a': 10.0, 'c': 2.0, 'b': 0.5}}

由于您希望按月计算平均值(此处考虑“dd-mm-yyyy”中的日期格式):

输出:

{'a': 5, 'c': 88, 'b': 15.143333333333333}
{'1': {'a': 11.666666666666666, 'c': 88.66666666666667, 'b': 15.143333333333333}, 
 '2': {'a': 10.0, 'c': 2.0, 'b': 0.5}}


您是否确实阅读了您提到的模块的文档?一对导入将启用两个明显的简化。非主题:不要使用dict.has_key,它在Python3中被弃用并删除。使用:
如果p在val\u点:
另外,看看你写的代码实际上不起作用
val_points=day[p]
将在第一次使用单个值替换dict,然后在下一次通过时引发异常,因为您试图将其用作dict…实际上,这里不需要任何模块。在
dict
(试试
help(dict)
看看你是否能找到它)上有一个方法,如果你试图写的东西乱七八糟的话,它会取代整个4行
,但是你甚至不需要它,因为你可以从
{'a':0,'b':0,'c':0}
dict.from_-keys('abc',value=0)
开始。然后,没有理由不在生成器表达式传递给
sum
时执行单独的循环,这是一个内置函数。(
operator
可以让这一点更好一些,但这不是必需的。)您是否确实阅读了您提到的模块的文档?一对导入将启用两个明显的简化。非主题:不要使用dict.has_key,它在Python3中被弃用并删除。使用:
如果p在val\u点:
另外,看看你写的代码实际上不起作用
val_points=day[p]
将在第一次使用单个值替换dict,然后在下一次通过时引发异常,因为您试图将其用作dict…实际上,这里不需要任何模块。在
dict
(试试
help(dict)
看看你是否能找到它)上有一个方法,如果你试图写的东西乱七八糟的话,它会取代整个4行
,但是你甚至不需要它,因为你可以从
{'a':0,'b':0,'c':0}
dict.from_-keys('abc',value=0)
开始。然后,没有理由不在生成器表达式传递给
sum
时执行单独的循环,这是一个内置函数。(
operator
可以让这一点更好一些,但这不是必要的。)我认为这不是OP想要的。他想要的是“一个月a、b和c的平均值”-对我来说,听起来像是每月一次。我以为他是指每个DICT列表都是一个月,他没有在自己的示例代码中拆分为几个月,他要求答案做同样的事情,我假设2014年2月1日是2月1日,2014年3月1日是3月1日,等等,但我明白你的意思。我想我们得让OP来启发我们。我的意思就是这样。忘记使用地图了,在rubyland呆了太久。我不认为这是OP要求的。他想要的是“一个月a、b和c的平均值”-对我来说,听起来像是每月一次。我以为他是指每个DICT列表都是一个月,他没有在自己的示例代码中拆分为几个月,他要求答案做同样的事情,我假设2014年2月1日是2月1日,2014年3月1日是3月1日,等等,但我明白你的意思。我想我们得让OP来启发我们。我的意思就是这样。忘记使用map了,在rubyland呆的时间太长了。
'd'
密钥来自哪里?用于测试不存在的密钥。我的错误。我编辑了输出。
'd'
键来自哪里?用于测试不存在的键。我的错误。我编辑了输出。