Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

MatrixPlot is very nice to have a first look of data, I would like to have a MatrixPlot with tooltips for each value. I tried adding Tooltip to all the values but it didn't work. My matrix is not very big (~20x25), so each square is visible.

EDIT: This is the version I did using the answer of Heike:

matPlot[matWithTooltips_, opts : OptionsPattern[]] := 
 With[{dim = Dimensions[matWithTooltips], 
   mat = matWithTooltips /. Tooltip[a_, ___] :> a},
  DynamicModule[{pt = {0, 0}, ij, xy, label, direction},
   direction[mxy_] := 1 - 2 Boole[Thread[mxy > dim/2]];
   LocatorPane[Dynamic[pt],
    Dynamic[
     xy = Floor[pt];
     ij = {dim[[1]], 1} + Cross[xy];
     label = If[And @@ Thread[1 <= ij <= dim],
       {{FaceForm[], EdgeForm[{Thick, LightGray}], Rectangle[xy]},
        Text[
         Framed[Replace[
           Extract[matWithTooltips, ij], {Tooltip[a_, b_] :> b, 
            Tooltip[a_] :> a}], Background -> White],
         direction[xy] + xy,
         -1.2 direction[xy]]},
       {}];
     MatrixPlot[mat, Epilog -> label, opts]],
    AutoAction -> True,
    Appearance -> None]]]

The main improvement is that it can receive a matrix with its own tooltips in the data.

Thanks to all for the help.

share|improve this question
add comment

5 Answers 5

up vote 12 down vote accepted

This is just an elaboration of faleichik's answer. To create a MatrixPlot with tooltip labelling and highlighting of the selected square similar to for example BarChart or BubbleChart you could do something like

matPlot[mat_, opts : OptionsPattern[]] :=
 With[{dim = Dimensions[mat]},
  DynamicModule[{pt = {0, 0}, ij, xy, label, direction},
   direction = 1 - 2 Boole[Thread[# > dim/2]] &;
   LocatorPane[Dynamic[pt],
    Dynamic[xy = Floor[pt];
     ij = {dim[[1]], 1} + Cross[xy];
     label = If[Nand @@ Thread[1 <= ij <= dim], {},
       (* else *)
       {{FaceForm[], EdgeForm[{Thick, LightGray}], Rectangle[xy]},
        Text[Framed[mat ~Extract~ ij, Background -> White],
         direction[xy] + xy, -1.2 direction[xy]]}];
     MatrixPlot[mat, Epilog -> label, opts]],
    AutoAction -> True,
    Appearance -> None]
   ]]

Screenshot

mat = RandomReal[1, {30, 40}];
matPlot[mat, ColorFunction -> "DeepSeaColors"]

screenshot

share|improve this answer
    
Very nice! Looking to the code: is there any particular reason to use With[] wrapping here? Why not include dim = Dimensions[mat] directly to DynamicModule? Am I missing something? –  faleichik Mar 2 '12 at 14:37
    
@faleichik No particular reason other than that With is usually more efficient for localizing constants than DynamicModule (although I don't think it would make any noticeable difference in this case). –  Heike Mar 2 '12 at 14:53
    
I like this a lot, but something I don't like is that when I changed the tooltip for something more complex, it got cut by the borders, maybe it could be fix to change the position of the tooltip towards the center of the image. I will try it. Thanks! –  FJRA Mar 2 '12 at 15:51
2  
I inserted a simple direction function instead of 1+xy and worked very nice! direction := 1 - 2 Boole[Thread[# > dim/2]] & and changed 1+xy -> direction[xy]+xy, {-1.2,-1.2} -> -1.2 direction[xy]. –  FJRA Mar 2 '12 at 17:48
3  
Why do I even bother to answer Graphics questions? +1 :-) –  Mr.Wizard Mar 2 '12 at 19:16
show 3 more comments

My variant is without tooltips but is fast. You need to click on the desired cell to get the value. One more advantage is that you have the generic MatrixPlot, not a substitute.

A = Table[Sin[x y/10 + x], {x, 1, 50}, {y, 1, 50}] // N;
{n, m} = Dimensions@A;
DynamicModule[{pt = {1, 1}/2, trans, ij},
 trans[{x_, y_}] := {Max[1, Min[n, Floor[n - y] + 1]],
   Max[1, Min[m, Floor@x + 1]]};
 Column@{
   LocatorPane[Dynamic[pt], MatrixPlot[A, ImageSize -> 500]], 
   Dynamic[(ij = trans@pt) -> A[[Sequence @@ ij]]]
   }
 ]

enter image description here


EDIT: more dynamic version without LocatorPane (no need to click) + using Clip as Mr.Wizard kindly adviced.

   A = Table[Sin[x y/10 + x], {x, 1, 50}, {y, 1, 50}] // N;
   {n, m} = Dimensions@A;
    DynamicModule[{pt = {1, 1}/2, trans, ij},
     trans[{x_, y_}] := {Clip[Floor[n - y] + 1, {1, n}],
       Clip[Floor@x + 1, {1, m}]};
     Column@{MatrixPlot[A, ImageSize -> 500],
       Dynamic[(ij = trans@MousePosition["Graphics", {0, 0}]) -> 
         A[[Sequence @@ ij]]]}
     ]

EDIT 2: using Appearance->None and Epilog, creating a stylish Tooltip in the right place, with the right alignment (you can probably do more to style it better if you want to spend the time).

A = Table[Sin[x y/10 + x], {x, 1, 50}, {y, 1, 50}] // N;
{n, m} = Dimensions@A;
DynamicModule[{pt = {1, 1}/2, trans, ij}, 
 trans[{x_, y_}] := {Max[1, Min[n, Floor[n - y] + 1]], 
   Max[1, Min[m, Floor@x + 1]]};
 gLoc[{x_, y_}] := {First@#, 1 + n - Last@#} &@Reverse@trans@{x, y};
 Column@{LocatorPane[Dynamic[pt], 
    MatrixPlot[A, ImageSize -> 500, 
     Epilog -> 
      Dynamic@{EdgeForm[Red], FaceForm[None], 
        Rectangle[gLoc@pt, gLoc@pt - 1], EdgeForm[Black], 
        FaceForm[{Opacity[.7], RGBColor[1, 1, .6]}], 
        If[First@gLoc@pt < n - 12,
         {Rectangle[gLoc@pt + {6, 2}, gLoc@pt + {-1, 0}], 
          Text[A[[Sequence @@ (trans@pt)]], gLoc@pt + {2, 1}]},
         {Rectangle[gLoc@pt + {-7, 2}, gLoc@pt], 
          Text[A[[Sequence @@ (trans@pt)]], gLoc@pt + {-3, 1}]}]}], 
    Appearance -> None, AutoAction -> True], 
   Dynamic[(ij = trans@pt) -> A[[Sequence @@ ij]]]}] 
share|improve this answer
    
Technically not tooltips, but quite possibly the better alternative. +1 –  Mr.Wizard Mar 2 '12 at 7:53
3  
Noted. You may care to know there is a built-in function for the Max[ Min [ ] ] thing: Clip[. . ., {1, m}] –  Mr.Wizard Mar 2 '12 at 8:21
4  
I like this approach. You could set AutoAction -> True in DynamicModule if you want the locator position to be continuously updated. Also, to mimic Tooltip, you could play around with Appearance in LocatorPane, or use Epilog to dynamically plot a label with the current value on top of the matrix plot. –  Heike Mar 2 '12 at 9:17
    
This is a very good alternative, since I can locate the "tooltip" above and use it as title comment. Thanks! –  FJRA Mar 2 '12 at 15:53
add comment

EDIT: y-axis corrected

You could do something like this:

a = RandomInteger[99, {7, 5}];

minmax = {Min@a, Max@a};
cf = ColorData["SunsetColors"];
ticks = Table[{i, # - i + 1}, {i, #}] & @ Length[a]

Graphics[
 {cf[1 - Rescale[#2, minmax]],
    Tooltip[Rectangle[# - 0.5], #2]} & @@@
      Most @ ArrayRules @ Reverse[a\[Transpose], {2}],
 Frame -> True,
 FrameTicks -> {All, ticks}
]

Mathematica graphics

share|improve this answer
    
+1. It is VERY hard to make something faster than you guys. Although this Tooltip aproach becomes very slow for large matrices. –  faleichik Mar 2 '12 at 7:22
    
@faleichik it is slow, but unless there is a specialized option for Raster I am overlooking I don't know of a better way. –  Mr.Wizard Mar 2 '12 at 7:28
    
I thought also about doing my own matrix plot, anyway I wanted to know if MatrixPlot could be adapted to have tooltips. Here would be necessary to add the MatrixPlot behavior for non numeric cases (like Indeterminate). Thanks! –  FJRA Mar 2 '12 at 15:58
add comment

One can also use the option CoordinatesToolOptions for MatrixPlot and make use of the Get Coordinates tool as follows:

 MatrixPlot[mat, ColorFunction -> "DeepSeaColors",
 CoordinatesToolOptions -> 
 {"DisplayFunction" ->
 Function[pt, 
 With[{rows = Dimensions[mat][[1]], columns = Dimensions[mat][[2]]},
 indices = {Clip[Floor[rows - pt[[2]]] + 1, {1, rows}], 
    Clip[Floor@pt[[1]] + 1, {1, columns}]};
  Row[{"mat[", Row[indices, ","], "]  =  ", Extract[mat, indices]},
   Background -> White, ImageSize -> {150, 30}, 
   Alignment -> Center]
  ]]}]

where I used faleichik's transformation.

Screenshot:

tooltip and get coordinates

Update: Generalizing, one can

  • Embed the needed coordinate transformations into DisplayFunction option for tooltips, and into CopiedValuesFunction option for copy/paste,
  • Use these user-specified functions as values for the CoordinatesToolOptions option in MatrixPlot, and
  • Let the Get Coordinates tool manage the dynamics needed for tooltips and copy/paste

as in:

  mtrxPlot2[mat_, opts : OptionsPattern[]] := 
  With[{dims = Dimensions[mat], 
  indx = {Clip[Floor[#1[[1]] - #2[[2]]] + 1, {1, #1[[1]]}], 
  Clip[Floor[#2[[1]]] + 1, {1, #1[[2]]}]} &}, 
  With[{copiedvalues = "CopiedValueFunction" -> Function[pt,
  {indx[dims, pt], Extract[mat, indx[dims, pt]]}], 
  coordtooltips = "DisplayFunction" -> Function[pt,
  Row[{"mat[[", Row[indx[dims, pt], ","], "]]  =  ", 
    Extract[mat, indx[dims, pt]]},
   Background -> White, ImageSize -> {Automatic, 30}, 
   ImageMargins -> {{5, 5}, {10, 10}}, Alignment -> Center]]}, 
  MatrixPlot[mat, opts, 
  CoordinatesToolOptions -> {coordtooltips, copiedvalues}]]]
share|improve this answer
    
This is really cool and a best answer IMO. –  faleichik Mar 4 '12 at 16:47
    
@faleichik, thank you. I like your and Heike`s LocatorPane approach better because it allows you to highlight the cells (which I do not know how to do with CoordinatesToolOptions) –  kguler Mar 5 '12 at 4:56
    
After trying it, I think it's very fast, but I had a problem, when using the output of this graphic into a GraphicsGrid, it looses the custom coordinates tooltips. Anyway this is the fastest one! –  FJRA Mar 6 '12 at 16:45
add comment

One way to do this:

is = 150; rm = RandomInteger[100, {5, 5}]; m =  Map[Tooltip[#, #] &, rm, {2}];
A = GraphicsGrid[m, ImageSize -> is {1, 1}]; B =  MatrixPlot[rm, FrameTicks -> None, 
Mesh -> All, PlotRangePadding -> 0, ImageSize -> is {1, 1}]; Overlay[{A, B}, All, 1]

enter image description here

It'll be a bit more elaborate to add frame ticks.

share|improve this answer
    
Good option, but tooltips only show up when you are in the center of the squares (if they are bigger than text numbers behind). I like that this is simple enough to be done without references once you know it :P. –  FJRA Mar 2 '12 at 15:55
1  
@FJRA Yes, thanks. Overlay is neat but often overlooked function - plus it preserves interactivity ;) –  Vitaliy Kaurov Mar 2 '12 at 22:33
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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