So numpy has some convenience functions for combining several arrays into one, e.g. hstack and vstack. I'm wondering if there's something similar but for stacking the component arrays diagonally?
Say I have N arrays of shape (n_i, m_i), and I want to combine them into a single array of size (sum_{1,N}n_i, sum_{1,N}m_i) such that the component arrays form blocks on the diagonal of the result array.
And yes, I know how to solve it manually, e.g. with the approach described in How to "embed" a small numpy array into a predefined block of a large numpy array? . Just wondering if there's an easier way.
Ah, How can I transform blocks into a blockdiagonal matrix (NumPy) mentions that scipy.linalg.block_diag() is the solution, except that the version of scipy installed on my workstation is so old it doesn't have it. Any other ideas?
It does seem block_diag
does exactly what you want. So if for some reason you can't update scipy, then here is the source from v0.8.0
if you wish to simply define it!
import numpy as npdef block_diag(*arrs):"""Create a block diagonal matrix from the provided arrays.Given the inputs `A`, `B` and `C`, the output will have thesearrays 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 ablock diagonal matrix.Parameters----------A, B, C, ... : array-like, up to 2DInput arrays. A 1D array or array-like sequence with length n istreated as a 2D array with shape (1,n).Returns-------D : ndarrayArray with `A`, `B`, `C`, ... on the diagonal. `D` has thesame dtype as `A`.References----------.. [1] Wikipedia, "Block matrix",http://en.wikipedia.org/wiki/Block_diagonal_matrixExamples-------->>> 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, 0for i, (rr, cc) in enumerate(shapes):out[r:r + rr, c:c + cc] = arrs[i]r += rrc += ccreturn out