寻找一种更高效/ Python化的方法来对列表中的元组求和,并计算平均值

时间:2018-11-03 10:18:31

标签: python list for-loop tuples urllib3

我正在尝试使用网络数据进行一些基本计算。为此,我发现了一些代码,这些代码提取了伦勃朗作品的开始和结束年份。它将其保存在列表中

date_list =[(work['datebegin'], work['dateend']) for work in `rembrandt2_parsed['records']]`

date_list是一个列表,其中包含伦勃朗在哈佛美术馆的某些作品的开始和结束年份的元组。为了完整起见,它看起来像这样:

[(0, 0), (1648, 1648), (1637, 1647), (1626, 1636), (0, 0), (1638, 1638), (1635, 1635), (1634, 1634), (0, 0), (0, 0)]

现在,我想进行一些基本计算,我想对这个元组列表求和,并计算不为空的年份的平均值。我想出了一个解决方案:

datebegin =0
date_end =0
count_begin =0
count_end =0

for x, y in date_list:
    if x !=0:
        datebegin +=x
        count_begin +=1
    if y != 0:
        date_end +=y
        count_end +=1

final_date_begin = datebegin/count_begin #value = year 1636
final_date_end = date_end/count_end #value = year 1639

但是我认为这可以更加高效/ Python化。首先,因为我似乎需要大量代码来完成这样一个简单的任务,其次,因为如果我这样做,则需要初始化4(!)全局var。 有人可以启发我并向我展示一种更有效的解决方法吗?

4 个答案:

答案 0 :(得分:2)

非numpy解决方案:

lst = [(0, 0), (1648, 1648), (1637, 1647), (1626, 1636), (0, 0), (1638, 1638), (1635, 1635), (1634, 1634), (0, 0), (0, 0)]

print(sum(x[0] for x in lst) / sum(x[0] != 0 for x in lst))
# 1636.3333333333333
print(sum(x[1] for x in lst) / sum(x[1] != 0 for x in lst))
# 1639.6666666666667

答案 1 :(得分:2)

脾气暴躁和列表理解是您的朋友。

import numpy as np  
date_list = [(0, 0), (1648, 1648), (1637, 1647), (1626, 1636), (0, 0), 
             (1638, 1638), (1635, 1635), (1634, 1634), (0, 0), (0, 0)]
final_date_begin = np.mean([x for x, y in date_list if not x == 0])
final_date_end = np.mean([y for x, y in date_list if not y == 0])

答案 2 :(得分:2)

在纯Python中

starts = [s for s, e in date_list for if s and e]
ends = [e for s, e in date_list for if s and e]

start_avg = sum(starts) / len(starts)
end_avg = sum(ends) / len(ends)

答案 3 :(得分:1)

您可以使用numpy解决此问题:

import numpy as np

result = list(np.ma.masked_equal(date_list, 0).mean(axis=0))

因此,这里我们首先将date_list存储在数组中,然后屏蔽掉零值,然后计算第一轴上的平均值。

对于您的样本数据,我们获得:

>>> list(np.ma.masked_equal(date_list, 0).mean(axis=0))
[1636.3333333333333, 1639.6666666666667]

性能:包含使用以下方法生成的包含10万个2元组的列表:

from random import randint

date_list = [(randint(0, 10), randint(0, 10)) for _ in range(100000)]

我们将此功能重复了1000次,并获得:

>>> timeit(f, number=1000)
51.31010195999988

所以在本地,这可以在每次运行51.3毫秒内处理100'000×2的“矩阵”。