I have a list of numbers, and I would like to plot them using ArrayPlot (which is easy, usually :)). I would like to be able to color the elements of the plot based on the average of the list: one color if the number is above average, another if it is below. I have tried a couple of things, but so far, no joy.

First thing I tried is have a module around the colorFun defined by me and the ArrayPlot, to calculate the mean, since I don't want it to be kernel-wide (many other plots will come with the same technique), and then define, inside the module, the colorFun:

  {a, mean, colorFun},
    a = RandomInteger[{0, 100}, 100];
    mean = Mean[a];
    colorFun[z_] := If[z <= mean, Red, Blue];
    ArrayPlot[List@a, ImageSize -> Full, ColorFunction -> colorFun]

but this didn't work, since the plot would return all in the same color. It's actually not clear to me why.

I also tried to move colorFun in the form:

colorFun[z_]=RGBColor[{ , , }]    

with 2 functions of z and mean for two elements and 0 for the third. The idea of using this approach instead of the if is that I could blend the colors (the further from the average, the more intense/bright the color I am plotting with).

Any ideas?


  • $\begingroup$ You need ColorFunctionScaling -> False... $\endgroup$ – PlatoManiac Apr 23 '13 at 10:33
  • 1
    $\begingroup$ ...or rewrite colorFun[] so that it takes arguments in the interval $[0,1]$. $\endgroup$ – J. M.'s ennui Apr 23 '13 at 10:42
  • 1
    $\begingroup$ Possible duplicate of Use ColorFunction in ListLinePlot with If $\endgroup$ – MarcoB May 23 '16 at 15:03

For concreteness, here's how one might do Plato's suggestion:

Module[{a, mid, colorFun},
       BlockRandom[SeedRandom[42]; (* for reproducibility *)
                   a = RandomInteger[{0, 100}, 100]];
       mid = Mean[a];
       colorFun[z_] := If[z <= mid, Red, Blue];
       ArrayPlot[{a}, ColorFunction -> colorFun, ColorFunctionScaling -> False]]

some array plot

To demonstrate the approach I proposed, I'll use it to implement your more fine-grained idea to have the color's intensity proportional to its distance from the mean, using Blend[]:

Module[{a, hi, lo, mid, colorFun},
                   a = RandomInteger[{0, 100}, 100]];
       {lo, mid, hi} = Through[{Min, Mean, Max}[a]];
       colorFun[z_] := Blend[{{0, Red}, {Rescale[mid, {lo, hi}], White}, {1, Blue}}, z];
       ArrayPlot[{a}, ColorFunction -> colorFun]]

another array plot with color intensity

  • $\begingroup$ Thanks! This providers a better scaling than my version. $\endgroup$ – mgm Apr 23 '13 at 11:12

I am now using this as a color function:

colorFun[z_] := Blend[{Red, Darker@Green}, (z - 1)/mean];

and it's working more or less fine. Please, never mind the noise, but maybe it will be useful for somebody else.

Also I am using, as suggested by PlatoManiac, ColorFunctionScaling -> False.


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.