I would like to have the vertical arrangement of colors in stacked bars match the arrangement of colors in the chart legend. But no matter what I try, they don't match. Here's the situation
BarChart[{{5, 37, 56}, {22, 49, 28}, {31, 60, 10}},
ChartLayout -> "Percentile",
ChartLegends -> Placed[{"1-Volume", "2-Area", "3-Length"}, Right],
ChartLabels -> {{"Before", "During", "After"}, None}]
In the real-world example the legend has quite a few more entries (6), so it would be nice if the order of the legend colors matched the order in the bars. I realize that I could set the ChartLegends to display at Bottom, but doesn't look good given the many legend entries.
Also, reversing the Legends list does not work as desired. The text of the legends was re-ordered, but the colors were not reordered (see below), so the legend captions no longer match the data in the chart.
Changing the order of the data (or the data and the legend items) does not work either.
Any suggestions?
BarChart[{{5, 37, 56}, {22, 49, 28}, {31, 60, 10}},
ChartLayout -> "Percentile",
ChartLegends -> {"1-Volume", "2-Area", "3-Length"},
ChartLabels -> {{"Before", "During", "After"}, None}] /.
Column[List[a : Grid[List[___]] ..]] :> Column[Reverse#List#a]
Edit
Remember to use FullForm when you want to mess up with Graphics/Chart/Plot internals
Building on the nice answer given by Belisarius, an alternative method using Part
bc[[2,1,1,1]]= Reverse#bc[[2,1,1,1]];bc
This may be inferred from FullForm and
Position[bc, #, Infinity]& /# {Framed[___],
Column[___],List[___,"1-Volume",___]}
or from any one of these, perhaps, and trial-and-error.
Although not part of the question, Simon's trick (see here) may be used to further manipulate the legend.
bc/.Labeled[g_,Framed[leg_],pos_]:>
Labeled[g,Framed[leg,FrameStyle->Orange,RoundingRadius->10,
Background->LightYellow],pos]
for example, gives the following:
Part may also be used to remove the frame around the legend (see this question)
but Simon's method is much more versatile.
bc[[2]]=bc[[2,1]];bc
You can use LegendContainer for this.
SetOptions[Legending`GridLegend,
Legending`LegendContainer -> (Framed#MapAt[Reverse, #, {1, 1}] &)];
BarChart[{{5, 37, 56}, {22, 49, 28}, {31, 60, 10}},
ChartLayout -> "Percentile",
ChartLegends -> {"1-Volume", "2-Area", "3-Length"},
ChartLabels -> {{"Before", "During", "After"}, None}]
Related
Please consider :
Needs["ErrorBarPlots`"];
list = {{223, 231, 167, 245, 292}, {90, 81, 88, 84, 106}}
Where the second list represent the StandardDeviation
ErrorListPlot[list // Transpose,
PlotRange -> {{0, 6}, {0, 500}}]
I find it very hard to customize those ErrorList Plot. So my ugly attempt to avoid using the package and achieve the filling I wanted :
ListPlot[{(list[[1]] - list[[2]]), (list[[1]] +
list[[2]]), list[[1]]}, Filling -> {1 -> {2}}, Joined -> True]
Questions :
Is there an " efficient" way to adjust the appearance using ErrorListPlot ?
If not How would you suggest handling error bar using ListPlot or BarChart ?
I have to mention that I use Joined so as to increase the visibility but, each point represent a different subject so they should not be but : Using ErrorListPlot I could not make the mean visible enough :-(
EDIT : #Sjoerd
You can use Filling with a normal ListPlot, not joined, to get vertical lines rather than area filling. Then style the dots as you like with PlotStyle. But also check out some of the options to ErrorListPlot. There are options to do what you need.
ErrorListPlot[list // Transpose, PlotRange -> {{0, 6}, {0, 500}},
PlotStyle -> {AbsolutePointSize[14], AbsoluteThickness[2]}]
According to the documentation, ErrorListPlot takes all the same options as ListPlot.
I'm trying to implement a DateListBarChart function that takes dated data and outputs a bar chart with the same placements as DateListPlot. It's essential that they plot data in the same horizontal position if given the same data, so they can be combined using Show. I am finding it difficult to get the settings for BarSpacing right so that the horizontal range of the plot doesn't change, and the bars stay in essentially the same place.
I have been unable to infer the correct scaling so that BarSpacing->{0.2,0.3} results in 20% of the x-axis length available for that group of bars is taken up with spacing between bars in that group, and 30% as spacing between groups of bars. For technical reasons I am doing this by passing things to RectangleChart. According to the documentation, BarSpacing is treated as absolute units in RectangleChart. Obviously the absolute sizes of the gaps need to be smaller if there are more series, and the bars need to be narrower.
Some examples:
arList = FoldList[0.9 #1 + #2 &, 0.01, RandomReal[NormalDistribution[0, 1], 24]]
{0.01, 0.334557, 2.02709, 1.1878, 1.9009, 3.08604, 2.36652, 3.04111,
3.32364, 3.22662, 3.12626, 2.59118, 1.69334, 1.21069, 0.23171,
0.689415, -0.852649, -0.124624, 0.58604, -0.481886, 0.221074,
-0.300329, 2.36137, 0.427789, -1.47747}
dists = RandomChoice[{3, 4}, Length[arList]]
{4, 4, 4, 3, 4, 3, 4, 3, 4, 4, 3, 4, 4, 3, 4, 4, 4, 4, 3, 4, 3, 3, 3, 3, 3}
Results in:
RectangleChart[Transpose[{dists - 0 - 0/2, arList}],
PlotRange -> {{0, 100}, {-2, 4}}, ChartStyle -> EdgeForm[None],
Frame -> True, GridLines -> Automatic, BarSpacing -> {0, 0}]
RectangleChart[Transpose[{dists - 0.7 - 0.5/2, arList}],
PlotRange -> {{0, 100}, {-2, 4}}, ChartStyle -> EdgeForm[None],
Frame -> True, GridLines -> Automatic, BarSpacing -> {0.7, 0.5}]
Notice how the data aren't spanning the same distance along the x-axis as the previous example.
It gets even messier when trying to chart multiple series (the same in this example, for illustration).
RectangleChart[
Transpose[{{dists - i/2 - j/2, arList}, {dists - i/2 - j/2,
arList}}, {2, 3, 1}], PlotRange -> {{0, 180}, {-2, 4}},
ChartStyle -> EdgeForm[None], Frame -> True, Ticks -> None,
GridLines -> Automatic, BarSpacing -> {i, j}]
I've been futzing for ages trying to find the right formula so that BarSpacing settings for the custom function (not seen here) induce the correct spacings and bar widths so that the horizontal plot range doesn't change as the BarSpacing does.
What am I missing?
EDIT: In response to belisarius, this is an example of where I am heading. It works, kind of (the bars aren't quite in alignment with the line, but this is probably the dates I am using) but the cases with stacked bars fail to plot with the bars where they should be, as do any kind of bar graph on its own where there are multiple series. (I'm quite proud of the date label placement algorithm: the powers that be at work don't want to give up that look.)
And here is one that just isn't working. The data should fill the horizontal range. (The different width bars are deliberate - it's a combination of annual and quarterly data.)
EDIT 2
I remember why I didn't use Filling in a DateListPlot to draw the bars as in Mike Honeychurch's package - if you have anything other than very skinny bars, they end up having the top edge in the wrong place.
DateListPlot[{dateARList},
PlotStyle -> {AbsolutePointSize[6], Yellow}, Filling -> {1 -> 0},
FillingStyle -> {1 -> {{AbsoluteThickness[12], Darker[Red, 0.25]}}},
PlotRange -> All]
Maybe using the ChartElementFunction option instead of BarSpacing helps. For example barplot in the code would plot a bar chart such that each bar has margins of gapl on the left and gapr on the right where gapl and gapr are fractions of the total width of the bar
scale[{{xmin_, xmax_}, {ymin_, ymax_}}, {gapl_, gapr_}] :=
{{xmin (1 - gapl) + xmax gapl, ymin}, {xmax (1 - gapr) + xmin gapr, ymax}}
barplot[dists_, arList_, {gapl_, gapr_}, opts___] :=
RectangleChart[Transpose[{dists, arList }], opts,
Frame -> True,
GridLines -> Automatic, BarSpacing -> 0,
ChartElementFunction -> (Rectangle ## scale[#, {gapl, gapr}] &)]
Usage:
To plot the original bar chart with no gaps
barplot[dists, arList, {0, 0}]
This would plot a bar chart with a margin of 0.2 on both sides which results in a bar chart with gaps of 0.4 times the total width of the bars. Note that the positions of the bars matches with those in the first figure.
barplot[dists, arList, {0.2, 0.2}]
You can plot multiple series by doing something like
Show[barplot[dists, arList 0.9, {0, 0.5}],
barplot[dists, arList 0.8, {0.5, 0}, ChartStyle -> LightGreen]]
You may relieve your complaint about FillingStyle by using CapForm["Butt"].
list = {0.01, -0.81, 0.12, 0.81, 1.79, 1.1, 0.41, 1., 1.33, 1.08,
2.16, 1.13, 1.92, 1.64, 1.31, 1.94, 1.71, 0.91, 2.32, 0.95, 1.29,
1.28, 2.97, 4.45, 5.11}
DateListPlot[list, {2000, 8},
PlotStyle -> {AbsolutePointSize[6], Yellow}, Filling -> {1 -> 0},
FillingStyle -> {1 -> {{CapForm["Butt"], AbsoluteThickness[14],
Darker[Red, 0.25]}}}, PlotRange -> {0, 6}, ImageSize -> 400]
I'm in the process of creating a notebook that contains a style to write documents. I would like Mathematica to behave similar to LaTeX in the sense that when I write a "Definition" cell then it will write "Definition [Chapter#].[Definition#]".
To see what I mean do the following. In an empty notebook create a cell and modify the style to "Chapter". You can do this by selecting the cell and the going to Format->Style->Other, enter "Chapter".
Now go to Format->Edit StyleSheet.... Enter Chapter in the input box. This will generate a cell labeled Chapter. Select that cell, and click on Cell->Show Expression. At this point select all that text that you see there and replace it with the following:
Cell[StyleData["Chapter"],
CellFrame->{{0, 0}, {0, 0}},
ShowCellBracket->Automatic,
CellMargins->{{42, 27}, {10, 30}},
CounterIncrements->"Chapter",
CounterAssignments->{{"Section", 0}, {"Definition", 0}},
FontFamily->"Verdana",
FontSize->24,
FontWeight->"Bold",
CellFrameLabels->{{
Cell[
TextData[{
"Chapter ",
CounterBox["Chapter"]
}], "ChapterLabel", CellBaseline -> Baseline], Inherited}, {
Inherited, Inherited}},
FontColor->RGBColor[0.641154, 0.223011, 0.0623026]]
This will change the style of how a chapter cell is displayed. I changed the color and font. The most important thing to me is the CellFrameLabels. Noticed that I have made it so that every time you create a chapter cell it will display: Chapter [Chapter Number].
In the picture above I have created several chapter cells and I have added the text: ": Title of Chapter #".
This is simple enough, we can create any cell, apply a definition and take advantange of counters to label the cells.
I have noticed how some books have definitions enclosed in box. So in this case I would like to create a box that contains Definition. Here is my lame attempt with the definition of the cell "Definition".
Cell[StyleData["Definition"],
CellFrame->{{0, 0}, {0, 2}},
ShowCellBracket->Automatic,
CellMargins->{{27, 27}, {0, 8}},
PageBreakWithin->False,
CellFrameMargins->16,
CellFrameColor->RGBColor[0.641154, 0.223011, 0.0623026],
Background->RGBColor[0.963821, 0.927581, 0.844465],
FontFamily->"Verdana",
CounterIncrements->"Definition",
FontSize->12,
CellFrameLabels->{{
Cell[
TextData[{
"Definition ",
CounterBox["Chapter"], ".",
CounterBox["Definition"]
}], "DefinitionLabel", CellBaseline -> Baseline], Inherited}, {
Inherited, Inherited}},
]
Here is how it looks in the notebook:
Here is the question: Is there a way to make the CellFrameLabels part of the cell? I want the label to have the same background and to be inline with the other text. Here is a screen shot of how I want it to look:
I have made the "label" bold font and blue. This is something that the user should not be able to modify.
I don't think that it's possible to do in the way you want. CellLabels can only be text, while both CellDingbat and CellFrameLabels can be arbitrary cell expressions.
Both CellDingbat -> ... and CellFrameLabels -> {{...,None},{None,None}} work if the cell is only a single line long. But do not automatically resize for multiple line cells (at least as far as I could tell). For example:
Cell["Abcdefg", "Text",
CellFrame->{{0, 1}, {0, 2}},
CellMargins->{{30, 24}, {6, 6}},
CellFrameMargins->0,
CellFrameColor->RGBColor[0, 0, 1],
CellFrameLabels->{{Cell[" Definition 1.1 ", "Text",
CellFrame -> {{2, 0}, {0, 2}}, CellFrameMargins -> 0], None}, {None, None}},
CellFrameLabelMargins->0,
Background->RGBColor[0, 1, 1]]
Putting a CellFrameLabel on the top does not have this problem, but I don't know how to align it to the left...
Cell["Abcde", "Text",
CellFrame->{{1, 1}, {0, 2}},
CellMargins->{{30, 24}, {6, 6}},
CellFrameMargins->0,
CellFrameColor->RGBColor[0, 0, 1],
CellFrameLabels->{{None, None}, {None,
Cell[" Definition 1.1 ", "Text",
CellFrame -> {{2, 2}, {0, 2}}, CellFrameMargins -> 0]}},
CellFrameLabelMargins->0,
Background->RGBColor[0, 1, 1]]
I think that maybe the best looking solution would be to include the "Definition ch.def:" in the cell contents.
Cell[TextData[{
Cell["Definition 1.1: ", Editable->False, Selectable->False, Deletable->False],
"Abcdefg"}], "Text",
CellFrame->{{1, 1}, {0, 2}},
CellMargins->{{30, 24}, {6, 6}},
CellFrameColor->RGBColor[0, 0, 1],
Background->RGBColor[0, 1, 1]]
Make it so that it's not deletable by the average user and it is probably almost as good as a cell(frame)label. It can include counters so that it automatically shows the correct numbering. The only problem is that it does not appear automatically, but if you just copy a pre-existing cell, then that's not too much of a problem.
Edit: Adding an input alias that creates the non-deletable counter
First we get the current input aliases,
oldAliases = InputAliases /. Options[EvaluationNotebook[], InputAliases];
then replace any existing alias EscdefEsc with our new one:
newAliases =
Append[DeleteCases[oldAliases, "def" -> _],
"def" -> Cell[TextData[
RowBox[StyleBox[#, FontWeight->"Bold", FontColor->Blue]&/#{"Definition ",
CounterBox["Chapter"], ".", CounterBox["Definition"], ": "}]],(*"Text",*)
Editable -> False, Selectable -> False, Deletable -> False]];
SetOptions[EvaluationNotebook[], InputAliases -> newAliases]
Since I don't have your style sheet, I need to set a couple of counters:
CellPrint[Cell["Setting the counters", "Text",
CounterAssignments -> {{"Chapter", 2}, {"Definition", 3}}]]
Now I can use the alias in an existing cell - it inherits the styling of the parent cell (unless otherwise specified):
Another option is to make a palette to go with your stylesheet. This would be useful since there's only a limited number of MenuCommandKey values that you can use for your new styles (n.b. overwriting the default ones will just confuse people). See this answer for an example of such a palette.
How do you plot legends for functions without using the PlotLegends package?
I, too, was disappointed by the difficulty of getting PlotLegend to work correctly. I wrote my own brief function to make my own custom figure legends:
makePlotLegend[names_, markers_, origin_, markerSize_, fontSize_, font_] :=
Join ## Table[{
Text[
Style[names[[i]], FontSize -> fontSize, font],
Offset[
{1.5*markerSize, -(i - 0.5) * Max[markerSize,fontSize] * 1.25},
Scaled[origin]
],
{-1, 0}
],
Inset[
Show[markers[[i]], ImageSize -> markerSize],
Offset[
{0.5*markerSize, -(i - 0.5) * Max[markerSize,fontSize] * 1.25},
Scaled[origin]
],
{0, 0},
Background -> Directive[Opacity[0], White]
]
},
{i, 1, Length[names]}
];
It is flexible, but not so easy to use. "names" is a list of strings to render in the legend; "markers" is a list with the same length as "names" of Graphics objects representing the plot markers or graphics to render; "origin" is a two-element list with the absolute horizontal and vertical position of the upper-left corner of the legend; "markerSize" is the number of points to scale the markers to; "fontSize" is the font size; "font" is the name of the font to use. Here is an example:
Plot[{x, x^2}, {x, 0, 2}, PlotStyle -> {Blue, Red},
Epilog -> makePlotLegend[
{x, x^2},
(Graphics[{#, Line[{{-1, 0}, {1, 0}}]}]) & /# {Blue, Red},
{0.9, 0.3},
12,
12,
"Arial"
]
]
I would also be very interested in an answer to this question.
To tell you what is wrong with PlotLegends: It is terribly unstable and in many instances doesn't work at all.
Here is an example where PlotLegends screws up completely. Output is from Mathematica 7.0:
Assume that we have measured some data points corresponding to a number of functions, and we want to show how well they compare to the ideal function, or maybe how well they match with a calculated fit. No problem! We'll just Show[] the smooth plot together with a ListPlot of the data points, right?
It could look something like this:
Show[
Plot[{Sin[x], Sinh[x]}, {x, -Pi, Pi}],
ListPlot[Join[{#, Sin[#]} & /# Range[-Pi, Pi, .5],
{#, Sinh[#]} & /# Range[-Pi, Pi, .5]]]
]
Now we'd like to put a legend on the plot, so readers will know what on earth they're looking at. Easier said than done, mister! Let's add the PlotLegend to the Plot[]:
Show[
Plot[{Sin[x], Sinh[x]}, {x, -Pi, Pi}, PlotLegend -> {Sin[x], Sinh[x]}],
ListPlot[Join[{#, Sin[#]} & /# Range[-Pi, Pi, .5],
{#, Sinh[#]} & /# Range[-Pi, Pi, .5]]]
]
This looks GREAT! Publish immediately!
For such a basic and ubiquitously needed functionality, it sure has been a lot of work to find an alternative to PlotLegend that just works. The best alternative I've found so far has been to meticulously construct a list of plotstyles, then construct the legend by hand, and finally to show it together with the plot using ShowLegend[]. (See for example here) It's possible, but a lot of work.
So if anyone knows of a workaround to make PlotLegend work, an alternative package that works better, or just a neat way to get legends that can be automated easily, I would be very grateful! It would certainly make life a little bit easier.
If you are experiencing the weird behavior described by James When you are trying to use 'Show' to combine two images, then you should play around with using the 'Overlay' function instead of 'Show'.
Alternatively, I have found that as long as both graphics have a legend then 'Show' will render the composite image correctly.
If it looks a bit silly having two legends then you can remove the one from the second graphic by using options like:
PlotLegend -> {},
LegendPosition -> {0.1, 0.1},
LegendSize -> 0.001,
LegendShadow -> None,
LegendBorder -> None
This creates an empty and invisible legend but still allows the two graphics to be composed correctly by 'Show'.
In Mathematica, how do you plot a horizontal line at a given number? How do you plot a vertical line at a given number?
If you're actually using Plot (or ListPlot, et c.), the easiest solution is to use the GridLines option, which lets you specify the x- and y-values where you want the lines drawn. For instance:
Plot[Sin[x], {x, 0, 2 \[Pi]},
GridLines -> {{0, \[Pi]/2, \[Pi], 3 \[Pi]/2, 2 \[Pi]},
{-1, -Sqrt[3]/2, -1/2, 0, 1/2, Sqrt[3]/2, 1}}]
EDIT to add:
Of course, this solution works if you just want to draw a line at a single, given number. For instance, if you want to reproduce the second example from dreeve's answer:
Plot[Sin[x], {x, 0, 2 Pi},
GridLines -> {{4}, {}}]
For the case of horizontal lines when using Plot the easiest trick is to just include additional constant functions:
Plot[{Sin[x], .75}, {x, 0, 2Pi}]
For vertical lines, there's the Epilog option for Plot and ListPlot:
Plot[Sin[x], {x, 0, 2Pi}, Epilog->Line[{{4,-100}, {4,100}}]]
But probably the best is the GridLines option given in Pillsy's answer.
One approach would be to add Line graphic primitives to your graphics:
p1 = Plot[Sin[x], {x, -2*Pi,2*Pi}];
l1 = Graphics#Line[{{-2Pi,.75},{2Pi,.75}}]; (* horizontal line at y==.75 *)
Show[p1,l1]
Another approach would be to fiddle around with GridLines.
Use the Gridlines command like so:
Plot[
1/(15*E^((x - 100)^2/450)*Sqrt[2*Pi]),
{x, 55, 145},
GridLines -> {{85, 115}, {}}
]
TRANSLATION
In the code above I plot a normal curve:
1/(15*E^((x - 100)^2/450)*Sqrt[2*Pi])
Then tell the plot what part of the x-axis I want it to display:
{x, 55, 145}
Then I add the vertical gridlines where I want them at 85 and 115.
GridLines -> {{85, 115}, {}}
Note you need to provide the blank {} where Gridlines would expect the horizontal grid lines locations.
An alternative is to think of the vertical line as a straight line of infinite slope. So for a vertical line at located at x=2*pi, we can do something like this:
Plot[{Sin[x], 10^10 (x - 2 \[Pi])}, {x, 0, 10}, PlotRange -> {-1, 1}]
click to see the image
Note that the term 10^10 mimics an infinite slope. If you do not use the option PlotRange -> {-1, 1}, the "dominant" function is the straight line so the Sin[x] function do effectively appears as an horizontal line.