【问题标题】:How to change part of numpy array without reshaping如何在不重塑的情况下更改 numpy 数组的一部分
【发布时间】:2022-01-17 15:06:57
【问题描述】:

我有以下数组

import numpy as np
import CustomClass

# Total = 24
height = 4
width  = 6
a = np.empty((height, width), dtype=object)

for row in range(self.height):
    for col in range(self.width):
        self.a[row, col] = CustomClass()

我想更改部分数组的属性(填充我的自定义类)。 例如,我想从 element[0,0] 开始更改 12 个元素,然后逐行更改。理想情况下,我会做一些类似的事情

change=11
for i in range(change):
   a[i].value=True

结果将类似于以下内容(0:未更改,x:已更改)

x x x x x x 
x x x x x 0
0 0 0 0 0 0
0 0 0 0 0 0

我的数组的问题在于,我首先需要将其展平,然后才能执行此类操作。或者我应该先计算多少列和行,然后才能索引数组本身。是否有一个 numpy 函数,这样我就可以逐个元素(逐行)迭代数组元素。

希望我的解释清楚吗?

【问题讨论】:

  • 如果你的 numpy 是 2-d,那么你可以计算(行数)的 mod 和列来做到这一点。但是有什么不使用 flatten 和 reshape 的具体原因吗?
  • 重塑或展平数组不会在内存中改变它,它只会改变元数据。您可以随心所欲地展平和重塑,而不会影响性能。
  • 性能和尝试学习新功能是提出这个问题的原因。但似乎扁平化和重塑就足够了。但是,我仍然需要使用 for 循环来更改 te 值。任何建议以不同的方式执行此操作,或者我不能避免 for 循环
  • 展平后,只要形状匹配,就可以像full_array[0:change] = new_values一样使用切片
  • 感谢您的建议,但是我的数组包含我想更改属性而不是用 new_values 替换它的对象

标签: python arrays numpy


【解决方案1】:

您可以通过多种方式做到这一点,但一种方法是使用np.unravel_index 来获取与展平的一维索引相对应的二维索引。我将在下面向您展示如何做到这一点。

首先创建您的数据:

from dataclasses import dataclass
import numpy as np

height = 4
width  = 6

@dataclass
class myClass:
    value: bool = False
        
data = np.asarray([myClass() for _ in range(height * width)])
data = data.reshape(height, width)

现在,将 change 设为要更改的索引数组,而不是要更改的元素数量:

change = np.arange(11)

确定与change 中的索引对应的二维索引:

rows, columns = np.unravel_index(indices=change, shape=(height, width))

然后您可以使用这些索引来迭代您想要更改的元素:

for element in data[rows, columns]:
    element.value = True

【讨论】:

  • 我喜欢这个答案,因为它让我学到了一些新东西 (np.ravel_index) 并完成了工作。谢谢
【解决方案2】:

您可以使用变量来计算有多少元素被更改并使用break 退出循环

import numpy as np


height = 4
width  = 6
a = np.empty((height, width), dtype=object)
a[:] = '0'

count = 0

for row in range(height):
    for col in range(width):
        count += 1
        a[row, col] = 'x'
        if count == 11:
            break
    if count == 11:
       break
    
print(a)        

结果:

[['x' 'x' 'x' 'x' 'x' 'x']
 ['x' 'x' 'x' 'x' 'x' '0']
 ['0' '0' '0' '0' '0' '0']
 ['0' '0' '0' '0' '0' '0']]

为了更简单,您可以在开始时设置count = 11,然后再减去,直到得到0

这样你只需要在一个地方设置11

import numpy as np

height = 4
width  = 6
a = np.empty((height, width), dtype=object)
a[:] = '0'

count = 11

for row in range(height):
    for col in range(width):
        count -= 1
        a[row, col] = 'x'
        if count == 0:
            break
    if count == 0:
       break
    
print(a)        

编辑:

您还可以计算必须更改的完整行数以及最后一行中必须更改的元素数。

import numpy as np

height = 4
width  = 6
a = np.empty((height, width), dtype=object)
a[:] = '0'

count = 11

rows = count // width
rest = count % width    

a[:rows] = 'x'
a[rows,:rest] = 'x'

print(a)

但是如果你想从不同的地方开始,那么这将不起作用[0,0]

【讨论】:

  • 使用嵌套循环听起来一点也不像 numpy-esque...
  • @AKX 如果它会创建矩形,那么它可以为此使用 numpy 函数。但与此同时,我创建了其他使用更多 numpy-esque 方法的方法a[:rows] = 'x' a[rows,:rest] = 'x'
  • 这似乎已经更好了。不过,您可以使用rows, rest = divmod(count, width)。 ;-)
  • 谢谢你的建议,我喜欢小编辑的版本。很有趣,尤其是 divmod。但是,我正在更改属性而不是设置值。那会奏效吗? object.value = True,是目标
猜你喜欢
  • 2022-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-11
  • 2021-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多