5
$\begingroup$

In a stacked bar chart, how do I give individual stacks separate colorings?

For example, how would I modify the following code

BarChart[{{4. 4, 0.7}, {3.5, 1.6, 1.2}}, ChartLayout->"Stacked"]

so each element in two stacks has its own color?

$\endgroup$
4
$\begingroup$

I like gwr's answer, but I thought it would be good to show how to do this with basic list manipulation.

data = {{4.4, 0.7}, {3.5, 1.6, 1.2}};
colors = {{Orange, LightBlue}, {Red, White, Blue}};
bars = MapThread[Style[#1, #2] & , #] & /@ Transpose[{data, colors}];
BarChart[bars, ChartLayout -> "Stacked"]

chart

$\endgroup$
  • $\begingroup$ I will accept this solution since I like the primitive list manipulation functions and they have the best backward compatibility. $\endgroup$ – user13892 Feb 3 at 20:35
  • $\begingroup$ I think following will also work. bars = Apply[Style,Transpose/@Transpose[{data,colors}],{2}] but I don't know which one is more efficient? $\endgroup$ – user13892 Feb 3 at 20:38
  • $\begingroup$ @user13892. Don't worry about efficiency in this case as the lists are not likely to be very long. Go with the code that looks best to you for reasons of readability and maintainability. Efficiency only becomes important when the lists have lengths in thousands or greater. $\endgroup$ – m_goldberg Feb 4 at 0:09
  • $\begingroup$ @user13892 Do you really find Apply[ Style, Transpose/@Transpose[{data,colors}],{2} ] good to read and maintain? There is a reason for having named slots and for people not using Assembler these days. ;-) $\endgroup$ – gwr Feb 4 at 12:27
6
$\begingroup$

While I am not sure whether you can address individual bars in a stacked bar start with ColorFunction the immediate way to color individual bars is to use the Style wrapper:

BarChart[ 
   { (* Bar 1 *)
       { Style[ 4.4, color1 ] , Style[ 0.7, color2 ] }
   , (* Bar 2 *)
       { Style[ 3.5, color3], Style[ 1.6, color4 ], Style[1.2, color5] }
   }
   , ChartLayout->"Stacked"
]

Where color1 to color5 can be color directives. Note: This is actually all the OP asked for and it is indeed backward compatible down to Version 7, when BarChart was introduced.

To make this more convenient and to use modern data structures that make data more readable and thus maintainable:

$barData = Association @@@ {
    {
         "Height" -> {4.4, 0.7},
         "Color" -> {Red, Blue}
    }
    ,
    {
        "Height" -> {3.5, 1.6, 1.2},
        "Color" -> {Yellow, Green, Pink}
    }
};

$bars =  Query[All, {#Height, #Color} & /* MapThread[Style] ] @ $barData;

BarChart[ $bars, ChartLayout -> "Stacked" ]

BarChart

EDIT

To follow the example given by m_goldberg in his answer, I would like to show how $barData as an Association can be build from list data:

$heightData = {{4.4, 0.7}, {3.5, 1.6, 1.2}};
$colorData = {{Red, Blue}, {Yellow, Green, Pink}};

$barData = MapThread[
    AssociationThread[ { "Height", "Color" }, { ## } ]&,
    { $heightData, $colorData }
]

{<|"Height" -> {4.4, 0.7}, "Color" -> {RGBColor[1, 0, 0], RGBColor[ 0, 0, 1]}|>, <|"Height" -> {3.5, 1.6, 1.2}, "Color" -> {RGBColor[1, 1, 0], RGBColor[0, 1, 0], RGBColor[ 1, 0.5, 0.5]}|>}

$\endgroup$
5
$\begingroup$

Using ColorFunction, as long as the individual values are distinct, the colors will be distinct.

BarChart[{{4.4, 0.7}, {3.5, 1.6, 1.2}}, 
 ChartLayout -> "Stacked",
 ColorFunction -> Function[{height}, ColorData["Rainbow"][height]]]

enter image description here

Or with a legend

Legended[
 BarChart[data = {{4.4, 0.7}, {3.5, 1.6, 1.2}}, 
  ChartLayout -> "Stacked",
  ColorFunction -> Function[{height}, ColorData["Rainbow"][height]]],
 BarLegend[{"Rainbow", MinMax[data]}]]

enter image description here

$\endgroup$
  • $\begingroup$ I was wandering how to do this with ColorFunction so the ColorFunction is taking the actual value of the bar. So if i put an association with <|value->color,...|> as my color function i will be able to explicitly define my colors? right. $\endgroup$ – user13892 Feb 3 at 20:34
3
$\begingroup$

FWIF, BarChart gives the desired result if the style directives are passed as metadata:

dm = Thread /@ Thread[data -> colors]

{{4.4 -> RGBColor[1, 0.5, 0], 0.7 -> RGBColor[0.87, 0.94, 1]}, {3.5 -> RGBColor[1, 0, 0], 1.6 -> GrayLevel[1], 1.2 -> RGBColor[0, 0, 1]}}

BarChart[dm, ChartLayout -> "Stacked"]

enter image description here

$\endgroup$

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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