【问题标题】:Array elementwise operations数组元素操作
【发布时间】:2012-11-25 23:29:10
【问题描述】:

我有两个相同形状的输入数组 x 和 y。我需要通过函数运行具有匹配索引的每个元素,然后将结果存储在第三个数组 z 中的这些索引处。完成此任务的最蟒蛇方式是什么?现在我有四个四个循环 - 我确信有一个更简单的方法。

x = [[2, 2, 2],
     [2, 2, 2],
     [2, 2, 2]]

y = [[3, 3, 3],
     [3, 3, 3],
     [3, 3, 1]]

def elementwise_function(element_1,element_2):
    return (element_1 + element_2)

z = [[5, 5, 5],
     [5, 5, 5],
     [5, 5, 3]]

我很困惑,因为我的函数只适用于单个数据对。我不能简单地将 x 和 y 数组传递给函数。

【问题讨论】:

  • numpy 数组默认是元素明智的。即x+y=z
  • 有没有希望可以做矩阵级别的运算?例如,z = x + y 在您上面的示例中有效。也许您可以向我们展示您的函数是什么,我们可以帮助您让它在矩阵上工作?

标签: python arrays numpy elementwise-operations


【解决方案1】:

一种“更简单的方法”是使用numpy.vectorize 创建一个支持 NumPy 的函数。 “ufunc”是元素函数的 NumPy 术语(参见文档here)。使用numpy.vectorize 可以让您使用逐个元素的函数来创建自己的 ufunc,其工作方式与其他 NumPy ufunc(如标准添加等)相同:ufunc 将接受数组并将您的函数应用于每对元素,它将像标准 NumPy 函数等一样进行数组形状广播。documentation page 有一些可能有用的用法示例。

In [1]: import numpy as np
   ...: def myfunc(a, b):
   ...:     "Return 1 if a>b, otherwise return 0"
   ...:     if a > b:
   ...:         return 1
   ...:     else:
   ...:         return 0
   ...: vfunc = np.vectorize(myfunc)
   ...: 

In [2]: vfunc([1, 2, 3, 4], [4, 3, 2, 1])
   ...: 
Out[2]: array([0, 0, 1, 1])
In [3]: vfunc([1, 2, 3, 4], 2)
   ...: 
Out[3]: array([0, 0, 1, 1])

【讨论】:

    【解决方案2】:

    (我猜你说的是简单的 python list,而不是 numpy.array

    递归总是让我们的生活更轻松:

    def operate_on_Narray(A, B, function):
        try:
            return [operate_on_Narray(a, b, function) for a, b in zip(A, B)]
        except TypeError as e:
            # Not iterable
            return function(A, B)
    

    用法:

    >>> x = [[2, 2, 2],
    ...      [2, 2, 2],
    ...      [2, 2, 2]]
    >>> 
    >>> y = [[3, 3, 3],
    ...      [3, 3, 3],
    ...      [3, 3, 1]]
    >>> operate_on_Narray(x, y, lambda a, b: a+b)
    [[5, 5, 5], [5, 5, 5], [5, 5, 3]]
    

    它适用于任何其他类型的维度数组:

    >>> operate_on_Narray([1, 2, 3], [4, 5, 6], lambda a, b: a*b)
    [4, 10, 18]
    

    【讨论】:

      【解决方案3】:

      以下来自 python 2.7.3 解释器会话的脚本说明了使用内置函数 map 将元素操作应用于二维矩阵元素。 (注:operator.add等价于问题中指定的elementwise_function,也等价于applier的第二次使用中的lambda表达式。)

      >>> import operator
      >>> def applier(a, b, op):
      ...     return map(lambda ro: map(op, ro[0], ro[1]), zip(a,b))
      ... 
      >>> applier(x, y, operator.add)
      [[5, 5, 2], [5, 4, 5], [6, 5, 5]]
      >>> x; y
      [[2, 2, 1], [2, 2, 2], [3, 2, 2]]
      [[3, 3, 1], [3, 2, 3], [3, 3, 3]]
      >>> applier(x, y, lambda p,q: p+q)
      [[5, 5, 2], [5, 4, 5], [6, 5, 5]]
      >>> applier(x, y, lambda p,q: p-q)
      [[-1, -1, 0], [-1, 0, -1], [0, -1, -1]]
      >>> applier(x, y, lambda p,q: p*q)
      [[6, 6, 1], [6, 4, 6], [9, 6, 6]]
      

      注意,上面有x,y如下:

      x=[[2, 2, 1], [2, 2, 2], [3, 2, 2]]
      y=[[3, 3, 1], [3, 2, 3], [3, 3, 3]]
      

      如前所述,上面的脚本来自 python 2.7.3 解释器会话。如果此代码在 python 3 中运行,它将改为返回地图对象。可以使用如下函数来查看数字:

      def itemize(m):
          return [itemize(e) for e in m] if hasattr(m, '__iter__') else m
      

      有了这个功能,声明

      itemize(applier(x, y, operator.add))
      

      返回

      [[5, 5, 2], [5, 4, 5], [6, 5, 5]]
      

      【讨论】:

      • 此方法返回“
      • @onurcanbektas,这是 python 3 vs 2 的结果。请参阅编辑以获取更多信息,当然也支持编辑!
      猜你喜欢
      • 2011-05-06
      • 2012-05-07
      • 2012-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-21
      相关资源
      最近更新 更多