【问题标题】:NumPy Array Indexing and ReplacingNumPy 数组索引和替换
【发布时间】:2015-10-31 12:05:36
【问题描述】:

我有一个 3d numpy 数组如下:

(3L, 5L, 5L)

如果一个元素在 3d 位置,例如,[150, 160, 170] 存在。如何将它们全部转换为[0,0,0]?

import numpy as np
a = np.ones((3,5,5))
a[0,2:4,2:4] = 150
a[0,0:1,0:1] = 150 #important!
a[1,2:4,2:4] = 160
a[2,2:4,2:4] = 170
print a

预期的结果应该是:

[[[ 1.  1.  1.  1.  1.]
  [ 1.  1.  1.  1.  1.]
  [ 1.  1.  0.  0.  1.]
  [ 1.  1.  0.  0.  1.]
  [ 1.  1.  1.  1.  1.]]

 [[ 1.  1.  1.  1.  1.]
  [ 1.  1.  1.  1.  1.]
  [ 1.  1.  0.  0.  1.]
  [ 1.  1.  0.  0.  1.]
  [ 1.  1.  1.  1.  1.]]

 [[ 1.  1.  1.  1.  1.]
  [ 1.  1.  1.  1.  1.]
  [ 1.  1.  0.  0.  1.]
  [ 1.  1.  0.  0.  1.]
  [ 1.  1.  1.  1.  1.]]]

【问题讨论】:

  • np.where(条件)
  • 问题和示例应该更清楚地表明[150,160,170] 必须一起出现。
  • @hpaulj 是的!他们应该在一起!!

标签: arrays numpy scipy scikit-image


【解决方案1】:

首先我会转换成一堆三元组:

b = np.reshape(a.transpose(2, 1, 0), [25,3])

然后找到你想要的值:

idx = np.where((b == np.array([150, 160, 170])).all(axis=1))

并替换为您想要的任何值:

b[idx] = 0

最后转换回原来的形状:

c = np.reshape(b, [5, 5, 3]).transpose(2, 1, 0) 

【讨论】:

    【解决方案2】:

    构建你的a:

    In [48]: a=np.ones((3,5,5))    
    In [49]: a[0,2:4,2:4]=150
    In [50]: a[1,2:4,2:4]=160
    In [51]: a[2,2:4,2:4]=170
    
    In [52]: a
    Out[52]: 
    array([[[   1.,    1.,    1.,    1.,    1.],
            [   1.,    1.,    1.,    1.,    1.],
            [   1.,    1.,  150.,  150.,    1.],
            [   1.,    1.,  150.,  150.,    1.],
            [   1.,    1.,    1.,    1.,    1.]],
    
           [[   1.,    1.,    1.,    1.,    1.],
            [   1.,    1.,    1.,    1.,    1.],
            [   1.,    1.,  160.,  160.,    1.],
            [   1.,    1.,  160.,  160.,    1.],
            [   1.,    1.,    1.,    1.,    1.]],
    
           [[   1.,    1.,    1.,    1.,    1.],
            [   1.,    1.,    1.,    1.,    1.],
            [   1.,    1.,  170.,  170.,    1.],
            [   1.,    1.,  170.,  170.,    1.],
            [   1.,    1.,    1.,    1.,    1.]]])
    

    所有位置的布尔值,第一维的值为[150,160,170]。关键是将其扩展为 3d、形状 (3,1,1),可以广播到 (3,5,5) 并与 a 进行比较:

    In [53]: I = a==np.array([150,160,170])[:,None,None]
    
    In [54]: I
    Out[54]: 
    array([[[False, False, False, False, False],
            [False, False, False, False, False],
            [False, False,  True,  True, False],
            [False, False,  True,  True, False],
            [False, False, False, False, False]],
    
           [[False, False, False, False, False],
            [False, False, False, False, False],
            [False, False,  True,  True, False],
            [False, False,  True,  True, False],
            [False, False, False, False, False]],
    
           [[False, False, False, False, False],
            [False, False, False, False, False],
            [False, False,  True,  True, False],
            [False, False,  True,  True, False],
            [False, False, False, False, False]]], dtype=bool)
    

    现在只需将值 True 的所有插槽更改为 0:

    In [55]: a[I]=0
    
    In [56]: a
    Out[56]: 
    array([[[ 1.,  1.,  1.,  1.,  1.],
            [ 1.,  1.,  1.,  1.,  1.],
            [ 1.,  1.,  0.,  0.,  1.],
            [ 1.,  1.,  0.,  0.,  1.],
            [ 1.,  1.,  1.,  1.,  1.]],
    
           [[ 1.,  1.,  1.,  1.,  1.],
            [ 1.,  1.,  1.,  1.,  1.],
            [ 1.,  1.,  0.,  0.,  1.],
            [ 1.,  1.,  0.,  0.,  1.],
            [ 1.,  1.,  1.,  1.,  1.]],
    
           [[ 1.,  1.,  1.,  1.,  1.],
            [ 1.,  1.,  1.,  1.,  1.],
            [ 1.,  1.,  0.,  0.,  1.],
            [ 1.,  1.,  0.,  0.,  1.],
            [ 1.,  1.,  1.,  1.,  1.]]])
    

    查看已删除答案的 cmets,我发现您确实想要一个所有 3 个值都匹配的情况。也就是说,与您的示例相反,可能还有其他插槽a[0,...] 是 150 等您不想更改。

    你仍然可以使用这个I,只需在第一个轴上取一个all:

    In [58]: a[:,I.all(axis=0)]=2
    
    In [59]: a
    Out[59]: 
    array([[[ 1.,  1.,  1.,  1.,  1.],
            [ 1.,  1.,  1.,  1.,  1.],
            [ 1.,  1.,  2.,  2.,  1.],
            [ 1.,  1.,  2.,  2.,  1.],
            [ 1.,  1.,  1.,  1.,  1.]],
    
           [[ 1.,  1.,  1.,  1.,  1.],
            [ 1.,  1.,  1.,  1.,  1.],
            [ 1.,  1.,  2.,  2.,  1.],
            [ 1.,  1.,  2.,  2.,  1.],
            [ 1.,  1.,  1.,  1.,  1.]],
    
           [[ 1.,  1.,  1.,  1.,  1.],
            [ 1.,  1.,  1.,  1.,  1.],
            [ 1.,  1.,  2.,  2.,  1.],
            [ 1.,  1.,  2.,  2.,  1.],
            [ 1.,  1.,  1.,  1.,  1.]]])
    

    从概念上讲,我的答案与接受的答案没有太大区别。这会将数组重新整形为 2d,因此可以使用 1d [150,160,170] 进行匹配。实际上它会自动重新整形为(1,3),可以再次广播(25,3)数组。转置和重塑是标准化此类问题格式的一种便捷方法,尽管通常没有必要。


    将最后一个动作分开可能会有所帮助:

    In [60]: J=I.all(axis=0)
    
    In [61]: J
    Out[61]: 
    array([[False, False, False, False, False],
           [False, False, False, False, False],
           [False, False,  True,  True, False],
           [False, False,  True,  True, False],
           [False, False, False, False, False]], dtype=bool)
    
    In [62]: a[:, J] = 3
    

    或使用 np.where 将布尔数组转换为 2 个索引列表:

    In [73]: jj=np.where(J)
    In [74]: jj
    Out[74]: (array([2, 2, 3, 3], dtype=int32), array([2, 3, 2, 3], dtype=int32))
    
    In [75]: a[:, jj[0], jj[1]] = 4
    

    a[:,jj] 不起作用,但 a[(slice(None),)+jj] 起作用。最后一个表达式构造了一个 3 元素元组,相当于 [75] 的。

    我还可以将J 扩展为与a 匹配的大小和形状:

    In [90]: K=J[None,...].repeat(3,0)
    In [91]: K
    Out[91]: 
    array([[[False, False, False, False, False],
            [False, False, False, False, False],
            [False, False,  True,  True, False],
            [False, False,  True,  True, False],
            [False, False, False, False, False]],
    
           [[False, False, False, False, False],
            ....]], dtype=bool)
    

    并使用a[K]。

    【讨论】:

    • 跟随a[:,I.all(axis=0)]=2 部分有点困难。不能使用I = a==np.array([150,160,170])[:,None,None] 预先获得索引并定义一些轴,如 (1,3)?
    • 我已经详细阐述了I.all 索引。
    猜你喜欢
    • 1970-01-01
    • 2020-09-30
    • 2012-11-14
    • 2014-10-01
    • 2017-08-06
    • 2018-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多