Changing the order of elements in a chart legend

In a stacked BarChart or Histogram the bars are stacked from bottom to top, while the legend entries are listed from top to bottom. Is there a way to make the legend entries go the other way round to improve the visual correspondence between the chart and the legend?

E.g.

{bottom,middle,top}=RandomReal[NormalDistribution[0,1],{3,200}];
Histogram[{bottom,middle,top},10,ChartLayout->"Stacked",ChartLegends->{"Bottom","Middle","Top"}]


-
–  belisarius Apr 20 '12 at 21:57
also related? –  TomD Apr 21 '12 at 7:23
This question might also be of interest –  TomD Apr 21 '12 at 8:06

Histogram[{bottom, middle, top}, 10,
ChartLayout -> "Stacked",
ChartLegends -> {"Bottom", "Middle", "Top"}] /.
Column[l_List] :> Column[Reverse@l]


-
Slick answer! +1 –  Eli Lansey Apr 20 '12 at 22:04
I just checked out that linked question. That's also a really slick answer! –  Eli Lansey Apr 20 '12 at 22:10
This is great, thanks. It seems so obvious now! –  Simon Woods Apr 21 '12 at 11:08
@SimonWoods It is not obvious at all if you don't run Histogram[...]//FullForm first :) –  belisarius Apr 21 '12 at 15:19

Using belisarius' method, if you want to reverse the order for all vertical legends you could use LegendingLegendContainer like this:

{bottom, middle, top} = RandomReal[NormalDistribution[0, 1], {3, 200}];

SetOptions[LegendingGridLegend,
LegendingLegendContainer -> (Framed[# /. Column[l_List] :> Column[Reverse@l]] &)
];

Histogram[{bottom, middle, top}, 10,
ChartLayout -> "Stacked",
ChartLegends -> {"Bottom", "Middle", "Top"}
]


-
Legending sounds like a pejorative adjective for the works of people like JK Rowling –  belisarius Apr 21 '12 at 2:14
+1 BTW (and n more charsssss) –  belisarius Apr 21 '12 at 2:15
@belisarius you always find something to make me laugh. :D –  Mr.Wizard Apr 21 '12 at 2:15

This solution will no longer work in Mathematica 9 because they now use SwatchLegend in FullForm. Instead, apply this:

Histogram[{bottom, middle, top}, 10, ChartLayout -> "Stacked",
ChartLegends -> {"Bottom", "Middle", "Top"}] /.
SwatchLegend[l1_List, l2_List, r1_Rule, r2_Rule] :>
SwatchLegend[Reverse[l1, 1], Reverse[l2, 1], r1, r2]


The integer parameter in Reverse[l1,1] and Reverse[l2,1] might have to be tweaked; in some cases I had to reverse within the second level instead of the first. //FullForm should give you enough hints.

-
Where can I learn more about this type of syntax, eg. the l1_List and ri_Rule stuff? I'm not exactly sure how this is working, nor do I know how to use FullForm to help figure this out. I'm trying to flip a legend on a ListLogLogPlot using SwatchLegend. –  skratch May 24 '13 at 17:08
Ah, I got it! Seems a regular Plot only has one Rule following the two List elements in the FullForm of SwatchLegend. Removing r2_Rule and r2 in the delayed replacement does the trick. –  skratch May 24 '13 at 17:47
Yea that is exactly right. –  DancingDarwin Jul 7 '13 at 21:27

belisarius beat me to the Column replacement rule method. An alternative method would be to use ShowLegend to construct the legend manually, taking the code for the layout from the FullForm of your original graphic. The ridiculously complex lokking color specifications happen to be the Mathematica defaults for bar charts.

ShowLegend[ Histogram[{bottom, middle, top}, 10,  ChartLayout -> "Stacked"],
{{{Graphics[{GrayLevel[0.9],
Directive[GrayLevel[0.85], EdgeForm[Opacity[0.7]], Opacity[0.5],
RGBColor[0.6, 0.5470136627990908, 0.24]],
Rectangle[{0, 0}, {1, 1}]}, {ImageSize -> 10}],
"Top"}, {Graphics[{GrayLevel[0.9],
Directive[GrayLevel[0.85], EdgeForm[Opacity[0.7]], Opacity[0.5],
RGBColor[0.6, 0.24, 0.4428931686004542]],
Rectangle[{0, 0}, {1, 1}]}, {ImageSize -> 10}],
"Middle"}, {Graphics[{GrayLevel[0.9],
Directive[GrayLevel[0.85], EdgeForm[Opacity[0.7]], Opacity[0.5],
RGBColor[0.2472, 0.24, 0.6]],
Rectangle[{0, 0}, {1, 1}]}, {ImageSize -> 10}], "Bottom"}},
LegendPosition -> {0.25, 0.2}, LegendBackground -> White,
LegendBorder -> None, LegendShadow -> None,
LegendSize -> {0.6, 0.35}, LegendBorder -> None,
LegendTextSpace -> 3}]


-

As pointed out, Belisarius' method no longer works on v9. But, there are built in tools that do not require additional manipulation to work. LineLegend, PointLegend, and SwatchLegend all accept the form

LegendFunction[{lbl1, lbl2, ...}, options]


where {lbl1, lbl2, ...} are the legend labels, and the legend function will pick up the styles of the chart/plot automatically. This also works with Automatic and "Expressions", where appropriate. The key here is that the three legends can be then interchanged at will, and additional options can be supplied to change how they are displayed. In this case, the option you are looking for is LegendLayout, specifically, "ReversedColumn":

Histogram[{bottom, middle, top}, 10, ChartLayout -> "Stacked",
ChartLegends ->
SwatchLegend[{"Bottom", "Middle", "Top"},
LegendLayout -> "ReversedColumn"
]
]
`

Or, if you are curious

-