【问题标题】:Numpy: is it possible to use numpy and ndarray to replace for a loop in this code snippet?Numpy:是否可以使用 numpy 和 ndarray 替换此代码片段中的循环?
【发布时间】:2011-07-20 03:15:02
【问题描述】:

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

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

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 可以接受单元格中的文本值吗?

【问题讨论】:

    标签: python performance numpy


    【解决方案1】:

    如果你想混合数据类型,你会想要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')])
    

    【讨论】:

      【解决方案2】:

      如果你比较两个 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
      

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

        • 感谢您指出错误的数组名称。修复了标题和内容
        猜你喜欢
        • 2020-09-16
        • 1970-01-01
        • 2021-05-17
        • 2018-10-11
        • 1970-01-01
        • 1970-01-01
        • 2021-11-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多