使用NumPy从Python中的两个配对列表中获得平均重复值

在过去,我已经面对自己dealing with averaging two paired lists并且我已经成功地使用了那里提供的答案.

然而,对于大(超过20,000)项目,程序有点慢,我想知道使用NumPy是否会使它更快.

我从两个列表开始,一个浮点数和一个字符串:

names = ["a", "b", "b", "c", "d", "e", "e"]
values = [1.2, 4.5, 4.3, 2.0, 5.67, 8.08, 9.01]

我正在尝试计算相同值的平均值,因此在应用它之后,我会得到:

result_names = ["a", "b", "c", "d", "e"]
result_values = [1.2, 4.4, 2.0, 5.67, 8.54]

我把两个列表作为结果示例,但是还有一个(名称,值)元组列表就足够了:

result = [("a", 1.2), ("b", 4.4), ("d", 5.67), ("e", 8.54)]

用NumPy做到这一点的最佳方法是什么?

解决方法:

使用numpy你可以自己编写一些东西,或者你可以使用groupby功能(来自matplotlib.mlab的rec_groupby函数,但速度要慢得多.对于更强大的groupby功能,也许看看pandas),我把它与Michael的答案进行了比较邓恩用字典:

import numpy as np
import random
from matplotlib.mlab import rec_groupby

listA = [random.choice("abcdef") for i in range(20000)]
listB = [20 * random.random() for i in range(20000)]

names = np.array(listA)
values = np.array(listB)

def f_dict(listA, listB):
    d = {}

    for a, b in zip(listA, listB):
        d.setdefault(a, []).append(b)

    avg = []
    for key in d:
        avg.append(sum(d[key])/len(d[key]))

    return d.keys(), avg

def f_numpy(names, values):
    result_names = np.unique(names)
    result_values = np.empty(result_names.shape)

    for i, name in enumerate(result_names):
        result_values[i] = np.mean(values[names == name])

    return result_names, result_values     

这是三个结果:

In [2]: f_dict(listA, listB)
Out[2]: 
(['a', 'c', 'b', 'e', 'd', 'f'],
 [9.9003182717213765,
  10.077784850173568,
  9.8623915728699636,
  9.9790599744319319,
  9.8811096512807097,
  10.118695410115953])

In [3]: f_numpy(names, values)
Out[3]: 
(array(['a', 'b', 'c', 'd', 'e', 'f'], 
      dtype='|S1'),
 array([  9.90031827,   9.86239157,  10.07778485,   9.88110965,
         9.97905997,  10.11869541]))

In [7]: rec_groupby(struct_array, ('names',), (('values', np.mean, 'resvalues'),))
Out[7]: 
rec.array([('a', 9.900318271721376), ('b', 9.862391572869964),
       ('c', 10.077784850173568), ('d', 9.88110965128071),
       ('e', 9.979059974431932), ('f', 10.118695410115953)], 
      dtype=[('names', '|S1'), ('resvalues', '<f8')])

并且似乎numpy对于此测试来说要快一点(并且预定义的groupby函数要慢得多):

In [32]: %timeit f_dict(listA, listB)
10 loops, best of 3: 23 ms per loop

In [33]: %timeit f_numpy(names, values)
100 loops, best of 3: 9.78 ms per loop

In [8]: %timeit rec_groupby(struct_array, ('names',), (('values', np.mean, 'values'),))
1 loops, best of 3: 203 ms per loop
上一篇:TensorfFlow 实战Google深度学习框架读书笔记三:MNIST手写数字识别


下一篇:召回率(Recall),精确率(Precision),平均正确率