Numpy:如何使用数组的最后一个维度作为值?

Posted

技术标签:

【中文标题】Numpy:如何使用数组的最后一个维度作为值?【英文标题】:Numpy: How can I use last dimension of an array as a value? 【发布时间】:2022-01-20 03:58:58 【问题描述】:

我有一个形状为[1080, 1920, 4] 的 3-D 数组,最后一个轴代表图片的 RGBA 通道,我有一个从 RGBA 值到 int 的 dict 映射,我想使用 np.vectorize 来转换这个数组到形状为[1080, 1920] 的二维数组,如何将数组作为二维数组传递,最后一维是向量化函数的列表?

array = [[[112,  25, 235, 255],
        [112,  25, 235, 255],
        [112,  25, 235, 255],
        ...,
        [ 35,  35,  30, 255],
        [ 41,  40,  37, 255],
        [ 39,  41,  37, 255]]
        ...,
        [ 35,  35,  30, 255],
        [ 41,  40,  37, 255],
        [ 39,  41,  37, 255]]]
dic = (35,  35,  30, 255): 1, (41,  40,  37, 255): 2
np.vectorize(lambda x: dic.get(tuple(x)))()

我应该将什么传递给最后一个()

【问题讨论】:

你的意思是需要将3D列表扁平化成2D列表,对吧,然后传入函数中,对吧? np.vectorize 是一个美化的for 循环。您对其他方法持开放态度吗? 听起来像array.reshape(-1, 4) 【参考方案1】:

一种使用numpy.apply_along_axis的方式:

# Data with (3, 3, 4)
array([[[112,  25, 235, 255],
        [112,  25, 235, 255],
        [112,  25, 235, 255]],

       [[ 35,  35,  30, 255],
        [ 41,  40,  37, 255],
        [ 39,  41,  37, 255]],

       [[ 35,  35,  30, 255],
        [ 41,  40,  37, 255],
        [ 39,  41,  37, 255]]])

dic = (112, 25, 235, 255): 0,
 (35, 35, 30, 255): 1,
 (41, 40, 37, 255): 2,
 (39, 41, 37, 255): 3

np.apply_along_axis(lambda x: dic.get(tuple(x)), 2, array)

输出:

array([[0, 0, 0],
       [1, 2, 3],
       [1, 2, 3]])

【讨论】:

numpy.apply_along_axis 确实有效,但似乎很慢,但感谢您的帮助【参考方案2】:

vectorize 通常将标量值传递给函数。但是你可以指定一个signature

In [55]: f=np.vectorize(lambda x: dic.get(tuple(x)),signature='(n)->()')

使用@Chris 示例值:

In [56]: f(arr)
Out[56]: 
array([[0, 0, 0],
       [1, 2, 3],
       [1, 2, 3]])

vectorize 警告signature 使用速度较慢:

In [57]: timeit f(arr)
178 µs ± 6.38 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

像@Chris 那样使用apply...

In [58]: timeit np.apply_along_axis(lambda x: dic.get(tuple(x)),2, arr)
131 µs ± 1.18 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

以及对“扁平化”数组的列表理解:

In [59]: timeit np.array([dic.get(tuple(x)) for x in arr.reshape(-1,4)]).reshape(ar
    ...: r.shape[:2])
35.3 µs ± 108 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

vectorize 的速度劣势随着更大的数组而消失,尽管我不知道这是否适用于signature 的情况。

【讨论】:

以上是关于Numpy:如何使用数组的最后一个维度作为值?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用迭代函数为同一维度的numpy数组分配新的不同值

如何从填充零的 3 维 numpy 数组创建 4 维 numpy 数组?

使用基于另一个维度的np.where设置numpy切片

numpy如何沿维度拆分数组?

如何将 N-D 数组的最后两个维度作为 2D 数组?

如何使用 numpy 或 pandas 创建(或更改)数组/列表的维度?