Numpy:是否可以使用numpy和ndarray替换此代码段中的循环?

时间:2011-07-20 03:15:03

标签: python performance numpy

我正在寻找更智能,更好的解决方案。

我想根据标签内容将不同的缩放因子应用于数字字段。希望以下代码可以说明我想要实现的目标:

PS = [('A', 'LABEL1', 20),
('B', 'LABEL2', 15),
('C', 'LABEL3', 120),
('D', 'LABEL1', 3),]

FACTOR = [('LABEL1', 0.1), ('LABEL2', 0.5), ('LABEL3', 10)]

d_factor = dict(FACTOR)

for p in PS:
        newp = (p[0], p[1], p[2]*d_factor[p[1]])
        print newp

这是一项非常简单的操作,但我需要在至少一百万行的数据集上执行它。

所以,当然,越快越好。

这些因素将提前知道,数量不会超过20至30个。

  1. 我们可以使用任何矩阵或linalg技巧吗?

  2. ndarray可以接受单元格中的文本值吗?

3 个答案:

答案 0 :(得分:4)

如果您想要混合数据类型,则需要structured arrays

如果您想要查找数组中匹配值的索引,则需要searchsorted

你的例子是这样的:

>>> import numpy as np
>>> PS = np.array([
    ('A', 'LABEL1', 20),
    ('B', 'LABEL2', 15),
    ('C', 'LABEL3', 120),
    ('D', 'LABEL1', 3),], dtype=('a1,a6,i4'))
>>> FACTOR = np.array([
    ('LABEL1', 0.1), 
    ('LABEL2', 0.5), 
    ('LABEL3', 10)],dtype=('a6,f4'))

您的结构化数组:

>>> PS
array([('A', 'LABEL1', 20), ('B', 'LABEL2', 15), ('C', 'LABEL3', 120),
       ('D', 'LABEL1', 3)], 
      dtype=[('f0', '|S1'), ('f1', '|S6'), ('f2', '<i4')])
>>> FACTOR
array([('LABEL1', 0.10000000149011612), ('LABEL2', 0.5), ('LABEL3', 10.0)], 
      dtype=[('f0', '|S6'), ('f1', '<f4')])

您可以访问这样的单个字段(或者您可以给它们命名;请参阅文档):

>>> FACTOR['f0']
array(['LABEL1', 'LABEL2', 'LABEL3'], 
      dtype='|S6')

如何在PS上执行FACTOR的查找(必须对FACTOR进行排序):

>>> idx = np.searchsorted(FACTOR['f0'], PS['f1'])
>>> idx
array([0, 1, 2, 0])
>>> FACTOR['f1'][idx]
array([  0.1,   0.5,  10. ,   0.1], dtype=float32)

现在只需创建一个新数组并乘以:

>>> newp = PS.copy()
>>> newp['f2'] *= FACTOR['f1'][idx]
>>> newp
array([('A', 'LABEL1', 2), ('B', 'LABEL2', 7), ('C', 'LABEL3', 1200),
       ('D', 'LABEL1', 0)], 
      dtype=[('f0', '|S1'), ('f1', '|S6'), ('f2', '<i4')])

答案 1 :(得分:1)

如果比较两个numpy数组,则会得到相应的索引。您可以使用这些索引进行集合操作。这可能不是最快的修改,但它简单明了。如果PS需要具有您显示的结构,则可以使用自定义dtype并使用Nx3数组。

import numpy as np

col1 = np.array(['a', 'b', 'c', 'd'])
col2 = np.array(['1', '2', '3', '1'])
col3 = np.array([20., 15., 120., 3.])

factors = {'1': 0.1, '2': 0.5, '3': 10, }

for label, fac in  factors.iteritems():
    col3[col2==label] *= fac

print col3

答案 2 :(得分:0)

我认为numpy不能帮助你。顺便说一句,它是ndarray,而不是nparray ...

也许你可以用发电机做到这一点。见http://www.dabeaz.com/generators/index.html