7
$\begingroup$

I would like to define a version of MatrixForm that prints entries equal to zero in gray. The definition

matrixform[X_] := MatrixForm[X /. entry_ /; entry == 0 -> Style[0, LightGray]]

produces an output that looks how I'd want, but it actually changes the entries, rather than just the way they are displayed, so one cannot just use the output of my matrixform via % in algebraic manipulations.

Ideally I'm looking for an answer that works for sparse arrays too, without the conversion to a normal array: at least, I'd like to be able to work with the output without having to convert it back to a sparse array.

Note that I don't want just all zeroes in my notebook to be formatted in gray (so I don't think I can use Format), and I don't want matrices to be formatted as above automatically either.


Edit. Here is an example of what I'm hoping to achieve:

A = SparseArray[{1,1}->x,{2,2}]
(* Out: SparseArray[..., Specified elements: 1, Dimensions: {2,2}] as usual *) 

% // matrixform
(* Out: MatrixForm of A with 0s shown in gray *)

2 %
(* Out: SparseArray[..., Specified elements: 1, Dimensions: {2,2}] as usual *)

% // matrixform
(* Out: MatrixForm of 2*A with 0s shown in gray *)
$\endgroup$
  • $\begingroup$ PS. I don't really understand if there's a difference between the tags output-formatting and formatting, so I've used both; feel free to edit them. $\endgroup$ – Jules Lamers Feb 5 '18 at 13:57
6
$\begingroup$

To get the % behavior you want, you need to create a wrapper, that is, a function that does not evaluate, but creates a nice format when it is rendered. The usual way to do this is to use MakeBoxes. Here is a version that should target only matrix entries, and also avoid evaluation leaks:

matrixForm /: MakeBoxes[matrixForm[x_List], StandardForm] := Replace[
    Replace[Hold[x], 0->Style[0, Red], {3}],
    Hold[z_] :> MakeBoxes[MatrixForm[z]]
]

Note that I used Red instead of LightGray to improve visualization for this answer. Now that matrixForm is a wrapper, you can add it to $OutputForms as suggested in (51898).

Unprotect[$OutputForms];
AppendTo[$OutputForms, matrixForm];
Protect[$OutputForms];

Example:

matrixForm[{{f[0], 0}, {1, 0}}]

enter image description here

And using %:

%

{{f[0], 0}, {1, 0}}

For SparseArray objects, you could add the following format:

matrixForm /: MakeBoxes[matrixForm @ SparseArray[a_, b_, back_, c__], StandardForm] := With[
    {new = SparseArray[a, b, Style[back, Red], c]},
    MakeBoxes[
        MatrixForm @ new,
        StandardForm
    ]
]

Example:

matrixForm[IdentityMatrix[3, SparseArray]]

enter image description here

Check %:

%

SparseArray[Automatic, {3, 3}, 0, { 1, {{0, 1, 2, 3}, {{1}, {2}, {3}}}, {1, 1, 1}}]

$\endgroup$
  • $\begingroup$ Very nice! Do also know how to make it work for displaying sparse arrays as well, without turning the % into normal form? $\endgroup$ – Jules Lamers Feb 5 '18 at 16:09
  • $\begingroup$ @JulesLamers See update $\endgroup$ – Carl Woll Feb 5 '18 at 16:17
  • $\begingroup$ Fantastic, that does exactly what I want. Thanks! $\endgroup$ – Jules Lamers Feb 5 '18 at 16:24
6
$\begingroup$
SeedRandom[0]

(m = RandomInteger[{0, 2}, {4, 4}]) // MatrixForm

enter image description here

Note that by using parentheses, the definition of m does not include the wrapper MatrixForm

matrixForm[x_List] := ((x /. 0 :> Style[0, LightGray]) // MatrixForm)

m // matrixForm

enter image description here

The wrappers, MatrixForm or matrixForm are only for display. If you want to use the matrix, use m. Any subsequent operation is done on m and the display is formatted using the wrapper.

(m2 = Transpose@m) // matrixForm

enter image description here

m == (m2 // Transpose)

(* True *)
$\endgroup$
  • $\begingroup$ I think that does more or less what my matrixform does. The problem is that such definitions alter the matrix you're displaying: the line after m // matrixform, writing e.g. 2 % gives {{4,4,2,2*Style[0,LightGray]},...} $\endgroup$ – Jules Lamers Feb 5 '18 at 14:07
  • $\begingroup$ Ad edit: Output formatted with MatrixForm can be used for algebraic manipulations. For example, starting from some sparse array a, even though the output of a // MatrixForm is nicely formatted, one can actually use that output in something like 2 % to get a sparse array whose entries are twice those of a. I am looking for something similar here, perferably without having to use parentheses as in(...) // matrixform, if possible $\endgroup$ – Jules Lamers Feb 5 '18 at 14:46
  • $\begingroup$ @JulesLamers - Then just use 2 % // matrixform $\endgroup$ – Bob Hanlon Feb 5 '18 at 15:00
  • 3
    $\begingroup$ @JulesLamers To get the % behavior you want, see (51898). $\endgroup$ – Carl Woll Feb 5 '18 at 15:19
  • $\begingroup$ @CarlWoll Thanks! That looks very relevant. (And complicated...) I'll take a better look at it later $\endgroup$ – Jules Lamers Feb 5 '18 at 15:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.