【问题标题】:Python object array of empty arrays空数组的 Python 对象数组
【发布时间】:2021-06-30 06:33:07
【问题描述】:

我正在尝试在不使用循环的情况下创建一个空数组的 numpy 数组。使用循环,我可以使用类似的简化操作

a = np.empty((3, 3), object)
for i in range(a.size):
    a.ravel()[i] = np.array([])

或者基于np.nditer的稍微复杂一点的方法:

a = np.empty((3, 3), object)
it = np.nditer(a, flags=['multi_index', 'refs_ok'])
for i in it:
    a[it.multi_index] = np.array([])

我似乎找不到允许我以矢量化方式进行此分配的索引表达式。

我尝试了以下方法:

>>> a[:] = np.zeros((0, 3, 3))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: could not broadcast input array from shape (0,3,3) into shape (3,3)
>>> a[..., None] = np.zeros((3, 3, 0))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: could not broadcast input array from shape (3,3,0) into shape (3,3,1)
>>> a = np.full((3, 3), np.array([]), object)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.9/site-packages/numpy/core/numeric.py", line 343, in full
    multiarray.copyto(a, fill_value, casting='unsafe')
  File "<__array_function__ internals>", line 5, in copyto
ValueError: could not broadcast input array from shape (0,) into shape (3,3)

即使np.nditer 也不允许我回信:

>>> a = np.empty((3, 3), object)
>>> for x in np.nditer(a, flags=['refs_ok'], op_flags=['readwrite']):
...    x[...] = np.array([])
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ValueError: could not broadcast input array from shape (0,) into shape ()

有没有办法以向量化的方式制作空数组的对象数组?

我正在寻找的确切输出是

array([[array([], dtype=float64), array([], dtype=float64), array([], dtype=float64)],
       [array([], dtype=float64), array([], dtype=float64), array([], dtype=float64)],
       [array([], dtype=float64), array([], dtype=float64), array([], dtype=float64)]], dtype=object)

出于这个问题的目的,我不在乎引用都是相同的数组还是不同的数组。

【问题讨论】:

  • 您所需的输出与形状数组 (3, 3, 0) 有何不同?
  • @ShlomiF:在单元分配上完全不同的行为,不同的形状,完全不同的内存布局等。例如,所需的数组实际上内容,你可以做的事情像a[0, 0] = 'asdf' 将东西存储在数组中。尝试使用形状为 (3, 3, 0) 的数组来执行此操作不会存储任何内容 - 它会在形状为 (0,) 的子数组上广播分配并将字符串存储在生成的 0 个单元格中。
  • 嗯,好点...

标签: python numpy dtype


【解决方案1】:

您可以通过将数组放入 另一个 数组中来获取 NumPy 的广播处理,将数组视为标量对象而不是广播源:

template = numpy.empty((), dtype=object)
element = numpy.array([], dtype=float)
template[()] = element

然后您可以执行广播分配以将element 数组存储在结果数组的每个单元格中:

result = numpy.empty((3, 3), dtype=object)
result[:] = template

广播逻辑将通过template 而不是element 进行广播。这会产生一个 3×3 result 对象 dtype 数组,其中每个单元格都包含对单个 element 数组的引用。

result = numpy.full((3, 3), template) 也可以,但它似乎比切片赋值更更多令人困惑,切片赋值已经非常令人困惑 - result 的单元格是否结束并不是很明显持有对templateelement 的引用。

【讨论】:

  • result 的所有元素都是同一个对象(同一个id)。这并不重要,因为对于这样的阵列几乎没有什么可以就地做的事情。好吧,就地重塑作品:result[0,0].shape=(0,2).
  • @hpaulj:确实。问题说这没关系:“就这个问题而言,我不在乎引用都是相同的数组还是不同的数组。”整个操作很奇怪,很难说这方面在上下文中是否很奇怪。
  • 所以为了避免 OP 的广播问题,被分配的对象本身必须是一个对象 dtype 数组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-01-24
  • 1970-01-01
  • 1970-01-01
  • 2018-11-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多