6
$\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 Answers 4

5
$\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$
4
  • $\begingroup$ I will accept this solution since I like the primitive list manipulation functions and they have the best backward compatibility. $\endgroup$
    – user13892
    Commented Feb 3, 2019 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
    Commented Feb 3, 2019 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
    Commented Feb 4, 2019 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
    Commented Feb 4, 2019 at 12:27
8
$\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$
6
$\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$
1
  • $\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
    Commented Feb 3, 2019 at 20:34
4
$\begingroup$

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

data = {{4.4, 1.2}, {3.5, 1.6, 1.2}};
colors = {{Red, Blue}, {Orange, Green , Yellow}};

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

enter image description here

BarChart[dm, ChartLayout -> "Stacked"]

enter image description here

$\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.