【问题标题】:Map numpy array with ufunc用 ufunc 映射 numpy 数组
【发布时间】:2012-08-31 01:08:30
【问题描述】:

我正在尝试使用 ufunc 有效地将 N * 1 numpy 整数数组映射到 N * 3 numpy 浮点数组。

到目前为止我所拥有的:

map = {1: (0, 0, 0), 2: (0.5, 0.5, 0.5), 3: (1, 1, 1)}
ufunc = numpy.frompyfunc(lambda x: numpy.array(map[x], numpy.float32), 1, 1)

input = numpy.array([1, 2, 3], numpy.int32)

ufunc(input) 给出一个 3 * 3 的 dtype 对象数组。我想要这个数组,但使用 dtype float32。

【问题讨论】:

  • mapinput 是 Python 内置函数。最好不要为这些名称分配新值,因为这样很难访问 Python 内置函数。
  • frompyfunc 的文档说“返回的 ufunc 总是返回 PyObject 数组”。不管这是什么邪恶的原因,有一个相当简单的解决方法:提交一个适当条目类型的输出矩阵作为out 参数。

标签: python numpy


【解决方案1】:

你可以使用np.hstack:

import numpy as np
mapping = {1: (0, 0, 0), 2: (0.5, 0.5, 0.5), 3: (1, 1, 1)}
ufunc = np.frompyfunc(lambda x: np.array(mapping[x], np.float32), 1, 1, dtype = np.float32)

data = np.array([1, 2, 3], np.int32)
result = np.hstack(ufunc(data))
print(result)
# [ 0.   0.   0.   0.5  0.5  0.5  1.   1.   1. ]
print(result.dtype)
# float32
print(result.shape)
# (9,)

【讨论】:

    【解决方案2】:

    如果您的映射是一个 numpy 数组,您可以为此使用花哨的索引:

    >>> valmap = numpy.array([(0, 0, 0), (0.5, 0.5, 0.5), (1, 1, 1)])
    >>> input = numpy.array([1, 2, 3], numpy.int32)
    >>> valmap[input-1]
    array([[ 0. ,  0. ,  0. ],
           [ 0.5,  0.5,  0.5],
           [ 1. ,  1. ,  1. ]])
    

    【讨论】:

      【解决方案3】:

      你可以使用ndarray花式索引来得到同样的结果,我认为它应该比frompyfunc更快:

      map_array = np.array([[0,0,0],[0,0,0],[0.5,0.5,0.5],[1,1,1]], dtype=np.float32)
      index = np.array([1,2,3,1])
      map_array[index]
      

      或者你可以只使用列表推导:

      map = {1: (0, 0, 0), 2: (0.5, 0.5, 0.5), 3: (1, 1, 1)}
      np.array([map[i] for i in [1,2,3,1]], dtype=np.float32)    
      

      【讨论】:

      • 输入列表非常大,所以我尽量避免创建中间列表或数组。
      【解决方案4】:

      除非我误读了文档,否则np.frompyfunc 在标量对象上的输出确实是:当使用ndarray 作为输入时,您将得到ndarraydtype=obj

      一种解决方法是使用np.vectorize 函数:

      F = np.vectorize(lambda x: mapper.get(x), 'fff')
      

      在这里,我们将F 的输出中的dtype 强制为3 个浮点数(因此是'fff')。

      >>> mapper = {1: (0, 0, 0), 2: (0.5, 1.0, 0.5), 3: (1, 2, 1)}
      >>> inp = [1, 2, 3]
      >>> F(inp)
      (array([ 0. ,  0.5,  1. ], dtype=float32), array([ 0.,  0.5,  1.], dtype=float32), array([ 0. ,  0.5,  1. ], dtype=float32))
      

      好吧,这不是我们想要的:它是三个浮点数组的元组(正如我们给出的 'fff'),第一个数组等同于 [mapper[i][0] for i in inp]。所以,通过一些操作:

      >>> np.array(F(inp)).T
      array([[ 0. ,  0. ,  0. ],
             [ 0.5,  0.5,  0.5],
             [ 1. ,  1. ,  1. ]], dtype=float32)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-10-13
        • 2018-06-10
        • 2011-02-15
        • 2018-08-31
        • 2013-01-18
        • 2013-11-07
        • 2014-08-25
        • 2021-08-05
        相关资源
        最近更新 更多