How can I create a ColorFunction using Blend?

As shown below, I am trying to find a cool way to show some variance weighted deviation from the mean. There are 10 attributes that I compute the distance for.

How can I add a color function such that it is progressively a darker shade of red when its value is negative (towards the left) and green when the value is positive (towards the right of the graphics)?

distance = {0.245, -0.235, 0.053, -0.048, -0.128,
-0.007, -0.075, -0.067,-0.005, 0.082}

Show[
Function[
attributes,
Graphics[
Rectangle[
{If[distance[[attributes]] < 0, distance[[attributes]]*10, 0],
attributes - 1},
{If[distance[[attributes]] < 0, 0, distance[[attributes]]*10],
attributes}
],
PlotRange -> {{-5, 5}, {0, 10}},
Epilog -> {White, Line[{{0, 0}, {0, 11}}]}
]] /@ Range[10],
Frame -> True]


-
Something like Blend[{Darker[Red], Lighter[Green]}, #] &? – J. M. Jan 30 '12 at 3:27

distance = {0.245, -0.235, 0.053, -0.048, -0.128, -0.007, -0.075, -0.067, -0.005, 0.082}

Show[Function[attributes,
Graphics[{Blend[{{-Max[Abs[distance]], Red}, {0, LightRed}, {0,
LightGreen}, {+Max[Abs[distance]], Green}},
distance[[attributes]]],
Rectangle[{If[distance[[attributes]] < 0,
distance[[attributes]]*10, 0],
attributes - 1}, {If[distance[[attributes]] < 0, 0,
distance[[attributes]]*10], attributes}],
PlotRange -> {{-5, 5}, {0, 10}}},
Epilog -> {White, Line[{{0, 0}, {0, 11}}]}]] /@ Range[10],
Frame -> True]


-
Oops, looks like J.M. beat me to it. – Cassini Jan 30 '12 at 3:34
I formatted your code. It is straightforward to do so, yourself: just indent the code by 4-spaces, or select the code and type ctrl+k. – rcollyer Jan 30 '12 at 3:37
He left a comment, not an answer. Yours wins by default. – rcollyer Jan 30 '12 at 3:38
Indeed, @rcollyer's right. ;) – J. M. Jan 30 '12 at 3:42

We can achieve such visual style with built-in tools, applying some color gradient along the rectangles. Using your data:

distance = {0.245, -0.235, 0.053, -0.048, -0.128,
-0.007, -0.075, -0.067,-0.005, 0.082}


BarChart will do the job:

BarChart[distance, ChartElementFunction -> ChartElementDataFunction[
AspectRatio ->1, Frame ->True, GridLines -> {Range[-.22, .24, .02], Automatic}]


The horizontal scale is a bit different than yours, but you can easily adjust it. I personally enjoy very much that just a few lines will do things like:

BarChart[RandomReal[{-1, 1}, {50, 50}], ChartLayout -> "Stacked", Axes -> None,
BarSpacing ->{0, 0}, PerformanceGoal ->"Speed", ChartStyle -> "AvocadoColors"]


That was a Documentation example.

-
How did you know about ChartElementDataFunction. I couldn't find it in documentation. – Mike Honeychurch Jan 30 '12 at 6:32
@MikeHoneychurch I now added a link to words "built-in tools" in the first line of the post to refer to the corresponding Documentation example. – Vitaliy Kaurov Jan 30 '12 at 6:49
Interesting that it turned up there but is not documented at ref/ChartElementFunction and doesn't seem to have its own documentation page explaining usage – Mike Honeychurch Jan 30 '12 at 7:00
@MikeHoneychurch If you search Documentation for ChartElementDataFunction - there will be many links. Because functions such as SectorChart3D have a special section in Documentation under Options dedicated to the usage of ChartElementDataFunction. But you're right - currently no separate article. – Vitaliy Kaurov Jan 30 '12 at 7:26
Just to qualify the comment at the start of this thread. I typed ?ChartElementDataFunction and this failed to return a description. – Mike Honeychurch Jan 30 '12 at 8:13

If you want red on the negative side and green on the positive side without having a transition from red to green, you could do something like

colorf = Blend[{Darker[Red, .7 #/Min[distance]],
Darker[Green, .7 #/Max[distance]]}, UnitStep[#]] & ;

BarChart[distance,
ColorFunction -> colorf,
ColorFunctionScaling -> False,
BarOrigin -> Left, Frame -> True, BarSpacing -> None]


-

Looking at David's answer, it seems to me that you might want to

1. explicitly target the maximum and minimum values in your dataset to be pure green and red, respectively; and
2. have a neutral color, like gray, as the color at 0, so as to avoid the brownish colors in the middle.

To that end, I used this for the color:

If[distance[[attributes]] < 0,
Blend[{{Min[distance], Red}, {0, Gray}}, distance[[attributes]]],
Blend[{{Max[distance], Green}, {0, Gray}}, distance[[attributes]]]]


-