I know that using the Insert menu, you can create a matrix with vertical and horizontal lines, but not a more generic partition, such as dividing a 4x4 matrix into 4 2x2 partitions. Nor, can MatrixForm
do any sort of partitioning. So, how would I go about programmatically displaying such a partitioned matrix? I would like to retain the ability of MatrixForm
to act only as a wrapper and not affect subsequent evaluations, but it is not strictly necessary. I suspect this would involve using a Grid
, but I haven't tried it.

- 10,475
- 4
- 48
- 75
2 Answers
So this is what I came up with. For a matrix M:
M = {{a, b, 0, 0}, {c, d, 0, 0}, {0, 0, x, y}, {0, 0, z, w}};
you construct two list of True/False values (with True for places where you want separators) that take two arguments; first the matrix and second a list of positions for separators.
colSep = Fold[ReplacePart[#1, #2 -> True] &,
Table[False, {First@Dimensions@#1 + 1}], #2] &;
rowSep = Fold[ReplacePart[#1, #2 -> True] &,
Table[False, {Last@Dimensions@#1 + 1}], #2] &;
Now the partitioned view using Grid[]
is made with the use of Dividers
:
partMatrix = Grid[#1, Dividers -> {colSep[#1, #2], rowSep[#1, #3]}] &;
This takes three arguments; first the matrix, second the list of positions for column dividers, and third the list of values for row dividers.
In order for it to display nicely you just wrap it in brakets and use MatrixForm:
MatrixForm@{partMatrix[M, {3}, {3}]}
Which does the 2by2 partitioning you mentioned.

- 4,246
- 6
- 29
- 42
-
I have to spend some time looking over how it works exactly, but it is certainly clever. Although, you do lose the nice feature of `MatrixForm` where you can use its results directly. Give me a couple of hours to be able to vote up again. – rcollyer Oct 20 '10 at 14:10
-
2The `Dividers` option can just take a list of positions for the dividers too, and you can even use styles: `Grid[M, Dividers -> {{3 -> True}, {3 -> Red}}]` – Michael Pilat Oct 20 '10 at 16:25
-
Good call, the Fold jiggery I pulled there was really just a first attempt to get something going. If you coded a better version of partMatrix, you could have it optionally inherit the Dividers option notation. – Timo Oct 20 '10 at 17:10
-
To get back to the original problem tough (and maybe this could be a question in itself), is there a way to have an object in Mathematica that has a different and separate form when it's displayed from when it's evaluated? – Timo Oct 20 '10 at 17:11
-
@Michael, which can be readily accomplished via `Thread[{3,4}-> True]`, for instance. That eliminates the need for `colSep` and `rowSep` for divider specifications of the form: `{{index_ ..}, style_}`. Also, `{{index_, style_} ..}` could be dealt with easily via `Rule @@@ {{index_, style_} ..}`. – rcollyer Oct 20 '10 at 17:22
-
@Timo, definitely a separate question. Do you want to post it, or should I? – rcollyer Oct 20 '10 at 17:23
-
@rcollyer Go ahead, I don't have time right now and it's related to your problem anyways. Would be interesting to get a good answer to it, though I have doubts as to whether that sort of thing is possible. – Timo Oct 20 '10 at 17:45
-
$Timo, There are two separate questions here. The first is an object that displays differently than it's evaluated. That's easy - use `Interpretation` or its low-level equivalents. (See, eg, http://www.feyncalc.org/FeynCalcBook/). The second is to make a display wrapper like "*Form". This might involve a CellPrint... – Simon Oct 20 '10 at 22:23
After playing around for far too long trying to make Interpretation
drop the displayed form and use the matrix when used in subsequent lines, I gave up and just made a wrapper that acts almost exactly like MatrixForm
. This was really quick as it was a simple modification of this question.
Clear[pMatrixForm,pMatrixFormHelper]
pMatrixForm[mat_,col_Integer,row_:{}]:=pMatrixForm[mat,{col},row]
pMatrixForm[mat_,col_,row_Integer]:=pMatrixForm[mat,col,{row}]
pMatrixFormHelper[mat_,col_,row_]:=Interpretation[MatrixForm[
{Grid[mat,Dividers->{Thread[col->True],Thread[row->True]}]}],mat]
pMatrixForm[mat_?MatrixQ,col:{___Integer}:{},row:{___Integer}:{}]:=
(CellPrint[ExpressionCell[pMatrixFormHelper[mat,col,row],
"Output",CellLabel->StringJoin["Out[",ToString[$Line],"]//pMatrixForm="]]];
Unprotect[Out];Out[$Line]=mat;Protect[Out];mat;)
Then the postfix command //pMatrixForm[#, 3, 3]&
will give the requested 2x2 partitioning of a 4x4 matrix. It maybe useful to change the defaults of pMatrixForm
from no partitions to central partitions. This would not be hard.
-
Actually, pMatrixForm should probably inherit the argument structure of Grid - then they can all be simply passed through. I might rewrite this later. – Simon Oct 21 '10 at 02:12
-
There's a typo, the entire function body of `pMatrixForm` must be wrapped in parantheses. (You have the closing one, but not the opener.) That said, referencing the output via `Out[
]` works as expected. But, setting `p = pMatrixForm[M, 3, 3]` sets `p` to `Null`. This is very close to what I was looking for. – rcollyer Oct 21 '10 at 03:03 -
Thanks for picking up the typo. Using `p = MatrixForm[M]` or `p = pMatrixForm[M,3,3]` is generally a bad idea since then you can't do much with `p`. It's best to use something like `(p=M)//pMatrixForm[#,3,3]&` or equiv `pMatrixForm[p=M,3,3]`. If you really do want to set `p = pMatrixForm[M,3,3]` to mean `p=M` you could remove the final semicolon and then suppress the output in the expression where you use it. If you want it to set `p` to the typeset form then just use my `pMatrixFormHelper`. – Simon Oct 21 '10 at 03:33
-
Well shucks, now I have to add this question to my favorites :). Thank you Simon for a great piece of education. – Timo Oct 21 '10 at 05:44
-
I'll have to play with it to see how that comes together. But, definitely a nice solution. – rcollyer Oct 21 '10 at 14:12