簡體   English   中英

嵌套字典中的平均值

[英]Average values in nested dictionary

我想創建一個新的值列表my_qty ,其中每個項目等於d[key]['qty']中所有值的平均值,其中d[key]['start date']my_dates中的值匹配。 我想我已經很近了,但是正掛在嵌套部分上。

import datetime
import numpy as np
my_dates = [datetime.datetime(2014, 10, 12, 0, 0), datetime.datetime(2014, 10, 13, 0, 0), datetime.datetime(2014, 10, 14, 0, 0)]

d = {
    'ID1' : {'start date': datetime.datetime(2014, 10, 12, 0, 0) , 'qty': 12},
    'ID2' : {'start date': datetime.datetime(2014, 10, 13, 0, 0) , 'qty': 34},
    'ID3' : {'start date': datetime.datetime(2014, 10, 12, 0, 0) , 'qty': 35},
    'ID4' : {'start date': datetime.datetime(2014, 10, 11, 0, 0) , 'qty': 40},
}

my_qty = []
for item in my_dates:
  my_qty.append([np.mean(x for x in d[key]['qty']) if d[key]['start date'] == my_dates[item]])

print my_qty

所需輸出:

[23.5,34,0]

要澄清每個請求的輸出:

[average of d[key]['qty'] where d[key]['start date '] == my_dates[0], average of d[key]['qty'] where d[key]['start date '] == my_dates[1], average of d[key]['qty'] where d[key]['start date '] == my_dates[2],]

用純python

簡單的方法是按日期將數量分組為字典:

import collections

quantities = collections.defaultdict(lambda: [])

for k,v in d.iteritems():
    quantities[v["start date"]].append(v["qty"])

然后在該字典上運行以計算均值:

means = {k: float(sum(q))/len(q) for k,q in quantities.iteritems()}

給予:

>>> means
{datetime.datetime(2014, 10, 11, 0, 0): 40.0,
 datetime.datetime(2014, 10, 12, 0, 0): 23.5,
 datetime.datetime(2014, 10, 13, 0, 0): 34.0}

如果您想變得聰明,可以通過保持當前均值和所見值的數量相加來一次計算均值。 您甚至可以在一個類中抽象它:

class RunningMean(object):
    def __init__(self, mean=None, n=0):
        self.mean = mean
        self.n = n

    def insert(self, other):
        if self.mean is None:
            self.mean = 0.0
        self.mean = (self.mean * self.n + other) / (self.n + 1)
        self.n += 1

    def __repr__(self):
        args = (self.__class__.__name__, self.mean, self.n)
        return "{}(mean={}, n={})".format(*args)

一遍您的數據將給您答案:

import collections
means = collections.defaultdict(lambda: RunningMean())
for k,v in d.iteritems():
    means[v["start date"]].insert(v["qty"])

與熊貓

真正簡單的方法是使用pandas庫,因為它是為類似這樣的事情制作的。 這是一些代碼:

import pandas as pd
df = pd.DataFrame.from_dict(d, orient="index")
means = df.groupby("start date").aggregate(np.mean)

給予:

>>> means
             qty
start date      
2014-10-11  40.0
2014-10-12  23.5
2014-10-13  34.0

單行答案:

mean_qty = [np.mean([i['qty'] for i in d.values()\
 if i.get('start date') == day] or 0) for day in my_dates] 

In [12]: mean_qty
Out[12]: [23.5, 34.0, 0.0]

or 0的目的是,如果沒有qty ,則返回0作為OP所需的值,因為空列表上的np.mean默認情況下返回nan

如果您需要速度,那么可以在jme的出色第二部分上進行構建(您可以這樣做(我不重新計算均值直到被要求)將他的時間減少了3倍):

class RunningMean(object):
    def __init__(self, total=0.0, n=0):
        self.total=total
        self.n = n

    def __iadd__(self, other):
        self.total += other
        self.n += 1
        return self

    def mean(self): 
        return (self.total/self.n if self.n else 0)

    def __repr__(self):
        return "RunningMean(total=%f, n=%i)" %(self.total, self.n)
means = defaultdict(RunningMean)
for v in d.values():
    means[v["start date"]] += (v["qty"])

Out[351]: 
[RunningMean(mean= 40.000000),
 RunningMean(mean= 34.000000),
 RunningMean(mean= 23.500000)]

這是一些可以幫助您的工作代碼:

for item in my_dates:
  nums = [ d[key]['qty'] for key in d if d[key]['start date'] == item ]
  if len(nums):
    avg = np.mean(nums)
  else:
    avg = 0
  print item, nums, avg

請注意, np.mean不適用於空白列表,因此您必須檢查要平均的數字的長度。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM