Numpy中的对角堆叠?
所以,numpy有一些方便的函数,可以把多个数组合并成一个,比如hstack和vstack。我在想有没有类似的功能,可以把数组斜着叠加起来呢?
假设我有N个数组,形状分别是(n_i, m_i),我想把它们合并成一个大的数组,大小是(sum_{1,N}n_i, sum_{1,N}m_i),这样这些小数组就能在结果数组的对角线上形成块状排列。
我知道怎么手动解决这个问题,比如可以参考如何把一个小的numpy数组嵌入到一个大数组的预定义块中?的做法。只是想知道有没有更简单的方法。
哦,如何把块转换成块对角矩阵(NumPy)提到scipy.linalg.block_diag()是个解决方案,但我工作站上安装的scipy版本太旧了,没有这个功能。还有其他的想法吗?
1 个回答
13
看起来 block_diag
正好能满足你的需求。所以如果你因为某些原因不能更新 scipy,这里有 v0.8.0
的源代码,你可以直接定义它!
import numpy as np
def block_diag(*arrs):
"""Create a block diagonal matrix from the provided arrays.
Given the inputs `A`, `B` and `C`, the output will have these
arrays arranged on the diagonal::
[[A, 0, 0],
[0, B, 0],
[0, 0, C]]
If all the input arrays are square, the output is known as a
block diagonal matrix.
Parameters
----------
A, B, C, ... : array-like, up to 2D
Input arrays. A 1D array or array-like sequence with length n is
treated as a 2D array with shape (1,n).
Returns
-------
D : ndarray
Array with `A`, `B`, `C`, ... on the diagonal. `D` has the
same dtype as `A`.
References
----------
.. [1] Wikipedia, "Block matrix",
http://en.wikipedia.org/wiki/Block_diagonal_matrix
Examples
--------
>>> A = [[1, 0],
... [0, 1]]
>>> B = [[3, 4, 5],
... [6, 7, 8]]
>>> C = [[7]]
>>> print(block_diag(A, B, C))
[[1 0 0 0 0 0]
[0 1 0 0 0 0]
[0 0 3 4 5 0]
[0 0 6 7 8 0]
[0 0 0 0 0 7]]
>>> block_diag(1.0, [2, 3], [[4, 5], [6, 7]])
array([[ 1., 0., 0., 0., 0.],
[ 0., 2., 3., 0., 0.],
[ 0., 0., 0., 4., 5.],
[ 0., 0., 0., 6., 7.]])
"""
if arrs == ():
arrs = ([],)
arrs = [np.atleast_2d(a) for a in arrs]
bad_args = [k for k in range(len(arrs)) if arrs[k].ndim > 2]
if bad_args:
raise ValueError("arguments in the following positions have dimension "
"greater than 2: %s" % bad_args)
shapes = np.array([a.shape for a in arrs])
out = np.zeros(np.sum(shapes, axis=0), dtype=arrs[0].dtype)
r, c = 0, 0
for i, (rr, cc) in enumerate(shapes):
out[r:r + rr, c:c + cc] = arrs[i]
r += rr
c += cc
return out