【问题标题】:Replace values of a numpy index array with values of a list用列表的值替换 numpy 索引数组的值
【发布时间】:2012-11-14 09:04:53
【问题描述】:

假设你有一个 numpy 数组和一个列表:

>>> a = np.array([1,2,2,1]).reshape(2,2)
>>> a
array([[1, 2],
       [2, 1]])
>>> b = [0, 10]

我想替换数组中的值,所以 1 被 0 替换,2 被 10 替换。

我在这里发现了类似的问题 - http://mail.python.org/pipermail//tutor/2011-September/085392.html

但是使用这个解决方案:

for x in np.nditer(a):
    if x==1:
        x[...]=x=0
    elif x==2:
        x[...]=x=10

给我一​​个错误:

ValueError: assignment destination is read-only

我猜那是因为我无法真正写入 numpy 数组。

附: numpy 数组的实际大小为 514 x 504,列表为 8。

【问题讨论】:

    标签: python numpy indexing


    【解决方案1】:

    好吧,我想你需要的是

    a[a==2] = 10 #replace all 2's with 10's
    

    【讨论】:

    • 当我这样做时,我得到“assignment destination is read-only”,你知道这是为什么吗?
    • 这比其他解决方案简单得多,谢谢
    • 如果我们想同时更改索引处的元素是给定 n 的倍数,我们会怎么做。像同时改变a[2],a[4],a[6]....对于n = 2.,应该怎么做?
    【解决方案2】:

    numpy 中的只读数组可以写成可写的:

    nArray.flags.writeable = True
    

    这将允许像这样的赋值操作:

    nArray[nArray == 10] = 9999 # replace all 10's with 9999's
    

    真正的问题不是赋值本身,而是可写标志。

    【讨论】:

      【解决方案3】:

      可以像这样重新映射整个数组,而不是一一替换值:

      import numpy as np
      a = np.array([1,2,2,1]).reshape(2,2)
      # palette must be given in sorted order
      palette = [1, 2]
      # key gives the new values you wish palette to be mapped to.
      key = np.array([0, 10])
      index = np.digitize(a.ravel(), palette, right=True)
      print(key[index].reshape(a.shape))
      

      产量

      [[ 0 10]
       [10  0]]
      

      Credit for the above idea goes to @JoshAdel。它比我原来的答案要快得多:

      import numpy as np
      import random
      palette = np.arange(8)
      key = palette**2
      a = np.array([random.choice(palette) for i in range(514*504)]).reshape(514,504)
      
      def using_unique():
          palette, index = np.unique(a, return_inverse=True)
          return key[index].reshape(a.shape)
      
      def using_digitize():
          index = np.digitize(a.ravel(), palette, right=True)
          return key[index].reshape(a.shape)
      
      if __name__ == '__main__':
          assert np.allclose(using_unique(), using_digitize())
      

      我以这种方式对这两个版本进行了基准测试:

      In [107]: %timeit using_unique()
      10 loops, best of 3: 35.6 ms per loop
      In [112]: %timeit using_digitize()
      100 loops, best of 3: 5.14 ms per loop
      

      【讨论】:

      • 感谢unutbu!我会接受你的回答,因为它更通用。干杯。
      • "index = np.digitize(a.reshape(-1,), palette)-1" 可以替换为 "index = np.digitize(a.reshape(-1,), palette) ,对=真)”,对吧? (=对吗?)
      • @PietroBattiston:因为a 中的每个值都在palette 中,所以我认为right=True 返回相同的结果。感谢您的改进!
      • 如果我们想改变给定 n 的倍数的索引值,例如 a[2],a[4],a[6],a[8].. ... 对于 n=2?
      【解决方案4】:

      我找到了另一个使用 numpy 函数 place 的解决方案。 (文档here

      在您的示例中使用它:

      >>> a = np.array([1,2,2,1]).reshape(2,2)
      >>> a
      array([[1, 2],
         [2, 1]])
      >>> np.place(a, a==1, 0)
      >>> np.place(a, a==2, 10)
      >>> a
      array([[ 0, 10],
             [10,  0]])
      

      【讨论】:

      • 这是完美而简单的。谢谢@Linda!
      【解决方案5】:

      您也可以使用np.choose(idx, vals),其中idx 是一个索引数组,指示应将vals 的哪个值放在它们的位置。但是,索引必须从 0 开始。还要确保idx 具有整数数据类型。所以你只需要这样做:

      np.choose(a.astype(np.int32) - 1, b)
      

      【讨论】:

        【解决方案6】:

        我无法设置标志或使用掩码修改值。最后我只是复制了一个数组。

        a2 = np.copy(a)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-09-30
          • 1970-01-01
          • 2018-01-25
          • 2013-09-12
          • 2021-11-19
          • 2021-12-17
          • 2016-11-27
          • 1970-01-01
          相关资源
          最近更新 更多