在numpy中替换子阵列

时间:2012-06-05 08:31:17

标签: python replace numpy indexing

给定一个数组,

>>> n = 2
>>> a = numpy.array([[[1,1,1],[1,2,3],[1,3,4]]]*n)
>>> a
array([[[1, 1, 1],
        [1, 2, 3],
        [1, 3, 4]],

       [[1, 1, 1],
        [1, 2, 3],
        [1, 3, 4]]])

我知道可以简洁地替换它中的值,

>>> a[a==2] = 0
>>> a
array([[[1, 1, 1],
        [1, 0, 3],
        [1, 3, 4]],

       [[1, 1, 1],
        [1, 0, 3],
        [1, 3, 4]]])

是否可以对阵列中的整行(最后一轴)执行相同的操作?我知道a[a==[1,2,3]] = 11将工作并用11替换匹配子数组的所有元素,但我想替换不同的子数组。我的直觉告诉我写下面的内容,但是会出现错误,

>>> a[a==[1,2,3]] = [11,22,33]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: array is not broadcastable to correct shape

总之,我想得到的是:

array([[[1, 1, 1],
        [11, 22, 33],
        [1, 3, 4]],

       [[1, 1, 1],
        [11, 22, 33],
        [1, 3, 4]]])

...和n当然通常比2大很多,其他轴也大于3,所以如果我不需要,我不想循环它们。< / p>


更新:[1,2,3](或我正在寻找的任何其他内容)并不总是在索引1处。示例:

a = numpy.array([[[1,1,1],[1,2,3],[1,3,4]], [[1,2,3],[1,1,1],[1,3,4]]])

3 个答案:

答案 0 :(得分:2)

你必须做一些更复杂的事情来实现你想要的东西。

您不能选择这样的数组切片,但可以选择所需的所有特定索引。

首先,您需要构造一个表示您要选择的行的数组。即

data = numpy.array([[1,2,3],[55,56,57],[1,2,3]])

to_select = numpy.array([1,2,3]*3).reshape(3,3) # three rows of [1,2,3]

selected_indices = data == to_select
# array([[ True,  True,  True],
#        [False, False, False],
#        [ True,  True,  True]], dtype=bool)

data = numpy.where(selected_indices, [4,5,6], data)
# array([[4, 5, 6],
#        [55, 56, 57],
#        [4, 5, 6]])

# done in one step, but perhaps not very clear as to its intent
data = numpy.where(data == numpy.array([1,2,3]*3).reshape(3,3), [4,5,6], data)

numpy.where的工作原理是从第二个参数中选择是否为true,第三个参数是否为false。

您可以使用从哪里选择3种不同类型的数据。第一个是与selected_indices形状相同的数组,第二个只是一个值(如2或7)。第一种是最复杂的,可以是可以广播成与selected_indices相同形状的形状。在这种情况下,我们提供了[1,2,3],它们可以堆叠在一起以获得形状为3x3的数组。

答案 1 :(得分:2)

使用np.all检查所有列是否具有True值进行比较,然后使用创建的掩码替换值,可以实现更高的性能:

mask = np.all(a==[1,2,3], axis=2)
a[mask] = [11, 22, 23]

print(a)
#array([[[ 1,  1,  1],
#        [11, 22, 33],
#        [ 1,  3,  4]],
# 
#       [[ 1,  1,  1],
#        [11, 22, 33],
#        [ 1,  3,  4]]])

答案 2 :(得分:0)

请注意,如果这是您想要的,您的代码示例不会创建您说它的数组。但是:

>>> a = np.array([[[1,1,1],[1,2,3],[1,3,4]], [[1,1,1],[1,2,3],[1,3,4]]])
>>> a
array([[[1, 1, 1],
        [1, 2, 3],
        [1, 3, 4]],

       [[1, 1, 1],
        [1, 2, 3],
        [1, 3, 4]]])
>>> a[:,1,:] = [[8, 8, 8], [8,8,8]]
>>> a
array([[[1, 1, 1],
        [8, 8, 8],
        [1, 3, 4]],

       [[1, 1, 1],
        [8, 8, 8],
        [1, 3, 4]]])
>>> a[:,1,:] = [88, 88, 88]
>>> a
array([[[ 1,  1,  1],
        [88, 88, 88],
        [ 1,  3,  4]],

       [[ 1,  1,  1],
        [88, 88, 88],
        [ 1,  3,  4]]])