# How to visualize/edit a big matrix as a table?

Is it possible to visualize/edit a big matrix as a table ? I often end up exporting/copying big tables to Excel for seeing them, but I would prefer to stay in Mathematica and have a similar view as in Excel. Note that I'm looking for a non commercial solution. Thanks

-

Based on the approach of F'x this is a version aimed rather at large arrays. It should perform reasonably well independent of the array size and lets one edit the given variable directly. Performance suffers only from the maximal number of rows and columns to be shown, which can be controlled with the second argument. I did choose to use the "usual" syntax for controllers with a Dynamic wrapper, which basically just serves as a Hold in the function definition pattern. With the Interpretation-wrapper it will evaluate to just the array it shows. There are a lot of possible improvements, so everyone is welcome to make such improvements. Here is the code:

editMatrix[Dynamic[m_], maxfields_: {10, 10}] :=
With[{maxrows = Min[maxfields[[1]], Length[m]],
maxcols =
If[(Depth[m] - 1) == 2, Min[maxfields[[2]], Length[m[[1]]]], 1]},
Interpretation[
Panel[DynamicModule[{rowoffset = 0, coloffset = 0},
Grid[{{If[Length@m > maxrows,
VerticalSlider[
Dynamic[rowoffset], {Length[m] - maxrows, 0, 1}]],
Grid[Table[
With[{x = i, y = j},
Switch[{i, j}, {0, 0}, Spacer[0], {0, _},
Dynamic[y + coloffset], {_, 0},
Dynamic[x + rowoffset], _,
If[(Depth[m] - 1) == 2,
InputField[Dynamic[m[[x + rowoffset, y + coloffset]
]
],
FieldSize -> 5],
InputField[Dynamic[m[[x + rowoffset]]], FieldSize -> 5]
]
]
],
{i, 0, maxrows}, {j, 0, maxcols}]]}, {Spacer[0],
If[Length@First@m > maxcols,
Slider[Dynamic[coloffset], {0, Length[m[[1]]] - maxcols,
1}]
]}}]
]
],
m]
];


You can test it with, e.g.:

a = RandomReal[1, {1000, 300}];

editMatrix[Dynamic[a], {10, 6}]


This will confirm that a will actually be changed when editing the corresponding InputField:

Dynamic[a[[1, 1]]]

-
This is great ! Thanks to you and F'x –  faysou Apr 4 '12 at 12:40
Nice. I've added code to use sliders only when necessary. –  celtschk Apr 5 '12 at 8:07
I've added also many small improvements below. –  faysou Apr 5 '12 at 9:23
I've added column vector editing capability to the function. For row vectors, just (obviously) transpose it. –  CHM Jun 24 '12 at 20:28

In order to provide a user-friendly way to edit a matrix, I usually do the following:

a = RandomReal[Range[0, 1], {5, 5}];
Grid[Array[InputField[Dynamic[a[[#1, #2]]], FieldSize -> 5] &, {5, 5}]]


Because Dynamic is used in there, the matrix stored in variable a is automatically modified if you changed any of the numbers in the input fields.

And taking into account all comments below (with thanks to celtschk, Heike and tkott), I wrote the following function:

editMatrix[m_?ArrayQ] := Module[{cells},
label[i_?IntegerQ] := If[i > 26, label[Quotient[i, 27]], ""] <> FromCharacterCode[65 + Mod[(i - 1), 26]];
cells = MapIndexed[InputField[Dynamic[a[[Sequence @@ #2]]], FieldSize -> 6] &, m, {2}];
PrependTo[cells, label /@ Range[Length[m]]];
cells = MapThread[Prepend, {cells, Join[{""}, Range[Dimensions[m][[2]]]]}];
Pane[Grid[cells], Scrollbars -> True, ImageSize -> {Full, 500}]
]


Now rows and columns are numbered Excel-style, and it has scrollbars:

-
Now to put that into a nice function: editMatrix[m_?ArrayQ] := Grid[Array[InputField[Dynamic[m[[#1, #2]]], FieldSize -> 6] &, Dimensions@m]] –  tkott Apr 3 '12 at 14:02
The following variant does not need access to the dimensions: Grid[MapIndexed[InputField[Dynamic[a[[Sequence@@#2]]],FieldSize->5]&,a,{2}]] –  celtschk Apr 3 '12 at 14:59
BTW, a way to disable Shift-Enter for that grid would be nice. It doesn't do anything meaningful anyway. –  celtschk Apr 3 '12 at 15:03
@F'x your updated solution looks nice! Two comments: the labels disappear when you scroll, and the display is slow for a big matrix (don't see how to avoid this using InputField, a built-in improved TableView could probably correct this). –  faysou Apr 3 '12 at 22:44
In your editMatrix function after your edit, you changed m by a, which is wrong. Something else, to make it work properly, you need to add Attributes[editMatrix] = {HoldAll}. It's a very nice solution! –  FJRA Apr 19 '12 at 13:36

Maybe the undocumented TableView is helpful:

TableView[RandomReal[{0, 1}, {100, 100}]]


See this post.

Or, as suggested in the comments, perhaps TableForm.

-
Or the documented TableForm. –  VLC Apr 3 '12 at 13:49
Nice find! Now I wonder what other "Views" there are... –  tkott Apr 3 '12 at 13:56
It did not take long to crash Mma 8.0.4 by editing the contents of the tableview. Very slow too. Looking forward to an official release of this expression, though! –  JxB Apr 3 '12 at 14:35
However, there are plenty of additional data manipulations that can be done with TableView. If you right-click on the table, you can sort, add or delete either columns or rows, etc. –  VLC Apr 3 '12 at 14:36
To easily copy a number matrix to Excel I use this ExcelForm[l_] := TableForm[Map[AccountingForm[#, NumberSigns -> {"-", ""}] &, l, {-1}]]; –  faysou Apr 3 '12 at 14:55

Here's a slight variation of Albert's answer in order to
- not need Dynamic in the function's first argument
- have letters like in Excel for the columns' labels
- the vertical slider is on the right
- a name of the variable is displayed on top of the panel
- smaller space between cells
- using OptionsPattern
- celtschk's improvement for not displaying slider if not needed.

The perspective of not needing Excel anymore for just viewing big tables is really appealing ...

integerToLetters[n_]:=
Module[{x},
x=IntegerDigits[n-1,26];
x[[;;-2]]-=1;
];

SetAttributes[GetSymbolName, HoldFirst];
GetSymbolName[symbol_] := ToString@HoldForm@symbol;

SetAttributes[editMatrix,HoldFirst];
Options[editMatrix]={"MaxFields"->{10,5},"ExcelColumnLabel"->True};
editMatrix[m_, OptionsPattern[]] :=
With[
{
maxrows = Min[OptionValue["MaxFields"][[1]], Length[m]],
maxcols = Min[OptionValue["MaxFields"][[2]], Length[m[[1]]]],
excelColumnLabel=OptionValue["ExcelColumnLabel"]
}
,
Interpretation[
Panel[
DynamicModule[{rowoffset = 0, coloffset = 0},
Grid[
{
{Style[GetSymbolName[m],Bold]}
,
{
Grid[
Table[
With[ {x = i, y = j},
Switch[{i, j},
{0, 0},
Spacer[0],
{0, _},
Dynamic[If[excelColumnLabel,integerToLetters[y + coloffset],y + coloffset]],
{_, 0},
Dynamic[x + rowoffset],
_,
InputField[Dynamic[m[[x + rowoffset, y + coloffset]]], FieldSize -> 7]
]
]
,
{i, 0, maxrows}, {j, 0, maxcols}
]
,
Spacings -> {0, 0}
]
,
If[Length@m>maxrows,VerticalSlider[Dynamic[rowoffset], {Length[m] - maxrows, 0, 1}]]
}
,
{If[Length@First@m>maxcols,Slider[Dynamic[coloffset], {0, Length[m[[1]]] - maxcols, 1}]]}
}
]
]
]
,
m
]
];


Example

metal = RandomReal[1, {1000, 300}];
editMatrix[metal]

-
Works very quick!!! And expression capacity is already there (you can enter whatever in your cells and it works nice). Now to replace excel let's add capacity for Column/Row references to cells :P. –  FJRA Apr 19 '12 at 13:42
A correct version of the integerToLetters function is in the accepted answer here mathematica.stackexchange.com/q/27485/66 –  faysou Dec 16 '13 at 17:12

Whereas TableView looks great, it seems very unstable. I edited a cell and pressed return (by accident more or less), and that caused a crash (on Mac).

So I would second the suggestion to use TableForm because it also allows editing if you take the output of

TableForm[RandomReal[{0, 1}, {30, 30}]]


by selecting its cell bracket and copying it. Then start a new cell by typing

a =


and paste the last output into it. Now you have the data in an input cell but still in the form of a grid. The cells can be edited by placing the cursor in them. The display is very bare-bones, but you can customize it to some extent with the TableSpacing option.

-

I am not keen on manually editing in big arrays, but if you just want to view one, perhaps this function grid is useful. It takes all options of Grid, and produces an adequately sized output cell that is easily scrolled:

  grid[m_?ArrayQ, opts : OptionsPattern[]] :=
CellPrint[
ExpressionCell[Grid[m, FilterRules[{opts}, Options[Grid]]],
CellFrame -> True, Background -> LightBlue,
PageWidth -> Infinity]];

-