How is the BarSpacing option really implemented in Mathematica?
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 spanni开发者_开发问答ng 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]
精彩评论