How to build a matrix from a set of vectors and other matrices using ArrayFlatten
TL;DR;
myArrayFlatten = Flatten /@ Flatten[#, {{1, 3}}] &
{x,y,z}
or {{x},{y},{z}}
is considered column vector.
Usage example:
v1 = {1, 2, 3}; vNew = {{4, 5}, {6, 7}, {8, 9}};
v4 = {10, 11, 12}; v5 = {13, 14, 15}; v6 = List /@ {16, 17, 18};
{
{v1, vNew, v1},
{v4, v5, v6, v1},
{vNew, vNew}
} // myArrayFlatten // MatrixForm
Flatten
approach:
The fact that it is not working is due to:
In
ArrayFlatten[{{m11, m12, ...},{m21, m22, ...},...}]
all the matrices m_ij in the same row must have the same first dimension, and matrices m_ij in the same column must have the same second dimension.
and
ArrayFlatten[a]
is normally equivalent toFlatten[a,{{1,3},{2,4}}]
is not our "normal(ly)" case! Beacuse it works when stated expicitly:
blocks = {{v1, vNew}, {v4, v5, v6}} // Replace[#, x_?VectorQ :> Transpose@List@x, {2}] &;
blocks // Flatten[#, {{1, 3}, {2, 4}}] &
blocks // ArrayFlatten
{{1,4,5},{2,6,7},{3,8,9},{10,13,16},{11,14,17},{12,15,18}} ArrayFlatten[{{{{1},{2},{3}},{{4,5},{6,7},{8,9}}},{{{10},{11},{12}},{{13},{14}, {15}},{{16},{17},{18}}}}]
Not always though, will fail for example for: {{v1, vNew}, {vNew, v6}}
. So let's just do the first flip and then Map
with Flatten
, so at the end you can use:
myArrayFlatten = Flatten /@ Flatten[#, {{1, 3}}] &
it automatically takes {x,y,z}
to be column vector.
I don't understand everything well enough that I can post here quick explanation but a good start to learn more is in Flatten command: matrix as second argument
old anser, working but ugly
I really don't know why it is not that simple :/.
I hope I've not missed anything, this function will help you if dimensions are ok. So don't expect anything like build block matrix.
toMatrix = Composition[
Join @@ # &,
Join[##, 2] & @@@ # &,
Replace[#, x_?VectorQ :> Transpose@List@x, {2}] &
]
Replace
part is only in case someone provides {x,y,z}
lists and want them to be column vectors.
toMatrix@{
{vNew, vNew, v1},
{v1, v4, v1, vNew}
} // MatrixForm
First a simpler way to get your first example:
(m = ArrayFlatten[Transpose /@ {{v1, v2, v3}, {v4, v5, v6}}, 1]) // MatrixForm
An alternative way to do @bill's undoing trick:
(m2 = ArrayFlatten[Transpose /@ {{v1, ## & @@ Transpose[vNew]}, {v4, v5, v6}}, 1]) // MatrixForm
Using ArrayReshape
as an alternative to ArrayFlatten
:
ArrayReshape[Transpose /@ {{v1, vNew}, {v4, v5, v6}}, {6, 3}] // MatrixForm
How about just breaking up the matrix and then reconstructing the same way. Here are your source vectors
v1 = {1, 2, 3}; vNew = {{4, 5}, {6, 7}, {8, 9}};
v4 = {10, 11, 12}; v5 = {13, 14, 15}; v6 = {16, 17, 18};
So now define and reconstruct:
{v2, v3} = Transpose[vNew];
ArrayFlatten[{Transpose@{v1, v2, v3}, Transpose@{v4, v5, v6}}, 1] // MatrixForm
If you want to do it all in one command:
ArrayFlatten[{Transpose@Partition[Flatten[{v1, Transpose@vNew}], 3], Transpose@{v4, v5, v6}}, 1]