4
$\begingroup$

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:

  Module[
  {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?

Thanks!

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

2 Answers 2

5
$\begingroup$

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},
       BlockRandom[SeedRandom[42];
                   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

$\endgroup$
1
  • $\begingroup$ Thanks! This providers a better scaling than my version. $\endgroup$
    – mgm
    Commented Apr 23, 2013 at 11:12
3
$\begingroup$

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.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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