查找python字典中非零值的平均值

时间:2014-08-22 20:50:18

标签: python dictionary

找到非零"表"的平均值的最快方法是什么?这个python词典中的值:

d = {"a":{"pen":12,"table":23},"b":{"pen":12,"table":0},"c":{"pen":16,"table":54}}

我想到:

count = sum(1 for inner_dict in d if d[inner_dict]["table"] > 0)
total = sum([d[inner_dict]["table"] for inner_dict in d if d[inner_dict]["table"] > 0])
average = total/count

结果应为(23 + 54)/ 2 = 38

3 个答案:

答案 0 :(得分:3)

filtered = [d[i]["table"] for i in d if d[i]["table"]<>0]
avg = sum(filtered)/len(filtered)

实际上并不需要&lt;&gt; 0但

答案 1 :(得分:3)

因为您要求最快,所以这里有一些时间安排。请注意,我在Windows 8上使用IPython和Python 3.3,运行i7-3770。另外,在旁注中,您不应该在Python 2.x上使用/进行除法,因为它会进行整数除法。请改用float(a)/b,或在文件顶部添加from __future__ import division

d = {"a": {"pen": 12, "table": 23}, 
     "b": {"pen": 12, "table": 0},
     "c": {"pen": 16, "table": 54}}

def method0():  # Your method
    count = sum(1 for inner_dict in d if d[inner_dict]["table"] > 0)
    total = sum([d[inner_dict]["table"] for inner_dict in d if d[inner_dict]["table"] > 0])
    average = total/count

def method1():
    count = 0
    total = 0
    for a in d.values():
        val = a['table']
        if val > 0:
            count += 1
            total += val
    average = total/ count

def method2():  # user3684792's/Padraic Cunningham's method
    filtered = [d[i]["table"] for i in d if d[i]["table"] > 0]
    average = sum(filtered)/len(filtered)   

# from functools import reduce  # If using Python 3
def method3():  # Sylvain Leroux's method
    n, s = reduce(lambda acc,v: (acc[0]+1,acc[1]+v["table"]) if v["table"] else acc,
                  d.values(),
                  (0, 0))
    average = s/n


%timeit method0()
# 10000 loops, best of 3: 23.9 us per loop

%timeit method1()
# 1000000 loops, best of 3: 756 ns per loop

%timeit method2()
# 10000 loops, best of 3: 22.5 us per loop

%timeit method3()
# 1000000 loops, best of 3: 1.29 us per loop

初步结论:使用for循环和简单加法(method1)比本例中的任何列表推导方法快得多。

这几乎是你所期望的。请注意,方法1和方法3只迭代数据一次,将它们全部收集起来。方法0和2迭代更多,因为他们采取一个过程来过滤掉他们想要的条目然后另一个过程来总结它们。

答案 2 :(得分:2)

仅迭代一次

n, s = reduce(lambda acc,v: (acc[0]+1,acc[1]+v["table"]) if v["table"] else acc,
              d.values(),
              (0.,0.))
print n, s, s/n

产:

2.0 77.0 38.5