如何在NumPy中堆叠不同长度的向量?

40 投票
6 回答
60255 浏览
提问于 2025-04-17 16:08

我该如何把形状为 (x,)n 个向量按列叠加在一起,其中 x 可以是任何数字呢?

举个例子,

from numpy import *
a = ones((3,))
b = ones((2,))

c = vstack((a,b)) # <-- gives an error
c = vstack((a[:,newaxis],b[:,newaxis])) #<-- also gives an error

hstack 可以正常工作,但它是在错误的维度上进行连接。

6 个回答

1

有一个新的库可以更高效地处理这种类型的数组:https://github.com/scikit-hep/awkward-array

7

一般来说,把不同长度的数组放在一起会有点模糊,因为数据的对齐可能很重要。Pandas 提供了不同的高级解决方案来处理这个问题,比如把多个系列合并成数据框。

如果你只是想从第一个元素开始填充列,我通常会先构建一个矩阵,然后再填充列。当然,你需要用空值(在这个例子中是 np.nan)来填充矩阵中的空白部分。

a = ones((3,))
b = ones((2,))
arraylist=[a,b]

outarr=np.ones((np.max([len(ps) for ps in arraylist]),len(arraylist)))*np.nan #define empty array
for i,c in enumerate(arraylist):  #populate columns
    outarr[:len(c),i]=c

In [108]: outarr
Out[108]: 
array([[  1.,   1.],
       [  1.,   1.],
       [  1.,  nan]])
43

简短的回答是:你不能这样做。NumPy 本身不支持不规则数组。

详细的回答:

>>> a = ones((3,))
>>> b = ones((2,))
>>> c = array([a, b])
>>> c
array([[ 1.  1.  1.], [ 1.  1.]], dtype=object)

这样做会得到一个数组,它的表现可能和你预期的不一样。例如,它不支持一些基本的方法,比如 sum(求和)或 reshape(重塑),你应该把它当作普通的 Python 列表 [a, b] 来处理(也就是说,遍历它来进行操作,而不是使用向量化的写法)。

有几种可能的解决方法;最简单的办法是把 ab 强制调整为相同的长度,可能可以使用 掩码数组 或者 NaN 来表示某些行中的某些索引是无效的。例如,这里是 b 作为一个掩码数组:

>>> ma.array(np.resize(b, a.shape[0]), mask=[False, False, True])
masked_array(data = [1.0 1.0 --],
             mask = [False False  True],
       fill_value = 1e+20)

这样可以和 a 进行堆叠,如下所示:

>>> ma.vstack([a, ma.array(np.resize(b, a.shape[0]), mask=[False, False, True])])
masked_array(data =
 [[1.0 1.0 1.0]
 [1.0 1.0 --]],
             mask =
 [[False False False]
 [False False  True]],
       fill_value = 1e+20)

(对于某些用途,scipy.sparse 也可能会很有趣。)

撰写回答