如何制作具有不同行大小的多维numpy数组?

dzh*_*lil 42 python arrays numpy

我想创建一个二维numpy数组数组,每行有不同数量的元素.

cells = numpy.array([[0,1,2,3], [2,3,4]])
Run Code Online (Sandbox Code Playgroud)

给出错误

ValueError: setting an array element with a sequence.
Run Code Online (Sandbox Code Playgroud)

cal*_*rus 27

我们现在问了这个问题差不多7年了,还有你的代码

cells = numpy.array([[0,1,2,3], [2,3,4]])
Run Code Online (Sandbox Code Playgroud)

在numpy 1.12.0,python 3.5中执行,不会产生任何错误并 cells包含:

array([[0, 1, 2, 3], [2, 3, 4]], dtype=object)
Run Code Online (Sandbox Code Playgroud)

您可以访问您的cells元素cells[0][2] # (=2).

如果要在新元素(即数组)可用时动态构建numpy数组列表,则可以使用以下命令替代tom10的解决方案append:

d = []                 # initialize an empty list
a = np.arange(3)       # array([0, 1, 2])
d.append(a)            # [array([0, 1, 2])]
b = np.arange(3,-1,-1) #array([3, 2, 1, 0])
d.append(b)            #[array([0, 1, 2]), array([3, 2, 1, 0])]
Run Code Online (Sandbox Code Playgroud)

  • 问题是你仍然不能使用d.mean(),d.flatten()等. (4认同)
  • 这是最优化的方式吗?numpy 数组仍然应该是统一长度的二维吗?如果是这样,存储可变长度数据的最佳方式是什么? (2认同)

Phi*_*ipp 25

虽然Numpy知道任意对象的数组,但它针对具有固定尺寸的均匀数字数组进行了优化.如果您确实需要数组数组,最好使用嵌套列表.但是,根据数据的预期用途,不同的数据结构可能更好,例如,如果您有一些无效的数据点,则使用屏蔽数组.

如果你真的想要灵活的Numpy数组,请使用以下内容:

numpy.array([[0,1,2,3], [2,3,4]], dtype=object)
Run Code Online (Sandbox Code Playgroud)

但是,这将创建一个存储列表引用的一维数组,这意味着您将失去Numpy的大部分好处(矢量处理,局部性,切片等).


tom*_*m10 13

这在Numpy中得不到很好的支持(根据定义,几乎在所有地方,"二维数组"都具有相等长度的所有行).Numpy数组的Python列表对您来说可能是一个很好的解决方案,因为这样您就可以获得Numpy的优势,您可以在其中使用它们:

cells = [numpy.array(a) for a in [[0,1,2,3], [2,3,4]]]
Run Code Online (Sandbox Code Playgroud)


Eri*_*rik 8

另一种选择是将您的数组存储为一个连续的数组,并存储它们的大小或偏移量。这需要更多关于如何操作数组的概念性思考,但是可以使大量的操作像具有不同大小的二维数组一样工作。在他们不能的情况下,np.split则可用于创建 calocedrus 推荐的列表。最简单的操作是 ufuncs,因为它们几乎不需要修改。这里有些例子:

cells_flat = numpy.array([0, 1, 2, 3, 2, 3, 4])
# One of these is required, it's pretty easy to convert between them,
# but having both makes the examples easy
cell_lengths = numpy.array([4, 3])
cell_starts = numpy.insert(cell_lengths[:-1].cumsum(), 0, 0)
cell_lengths2 = numpy.diff(numpy.append(cell_starts, cells_flat.size))
assert np.all(cell_lengths == cell_lengths2)

# Copy prevents shared memory
cells = numpy.split(cells_flat.copy(), cell_starts[1:])
# [array([0, 1, 2, 3]), array([2, 3, 4])]

numpy.array([x.sum() for x in cells])
# array([6, 9])
numpy.add.reduceat(cells_flat, cell_starts)
# array([6, 9])

[a + v for a, v in zip(cells, [1, 3])]
# [array([1, 2, 3, 4]), array([5, 6, 7])]
cells_flat + numpy.repeat([1, 3], cell_lengths)
# array([1, 2, 3, 4, 5, 6, 7])

[a.astype(float) / a.sum() for a in cells]
# [array([ 0.        ,  0.16666667,  0.33333333,  0.5       ]),
#  array([ 0.22222222,  0.33333333,  0.44444444])]
cells_flat.astype(float) / np.add.reduceat(cells_flat, cell_starts).repeat(cell_lengths)
# array([ 0.        ,  0.16666667,  0.33333333,  0.5       ,  0.22222222,
#         0.33333333,  0.44444444])

def complex_modify(array):
    """Some complicated function that modifies array

    pretend this is more complex than it is"""
    array *= 3

for arr in cells:
    complex_modify(arr)
cells
# [array([0, 3, 6, 9]), array([ 6,  9, 12])]
for arr in numpy.split(cells_flat, cell_starts[1:]):
    complex_modify(arr)
cells_flat
# array([ 0,  3,  6,  9,  6,  9, 12])
Run Code Online (Sandbox Code Playgroud)