From: Luci Ellis on 1 Nov 2009 04:03 Dear MathGroupers, I am trying to set up some custom functions/ option settings to replicate the standard look and feel of charts as used by my employer. These are currently done in DeltaGraph, but I would like to be able to generate charts directly in Mathematica so that I don't have to worry about the additional (Export to Excel -> Import into DeltaGraph -> bother a research assistant ) steps. Most of our charts are of time series, and I have been able to replicate the look for line graphs by customising DateListPlot[]. But I can't replicate the effect for bar charts. Our standard is to put a tick every X periods (say, to mark off every year or every quarter) and then centre the date label in that region. I am having serious problems putting the ticks in exactly the right place for bar charts. Adding up bar widths and (prespecified) BarSpacings never quite seems to work. (If you need an example of what I'm trying to do, have a look at the two graphs on the left-hand side of the first page in http://www.rba.gov.au/ChartPack/output_expenditure_activity_fincon.pdf -- I have the equivalent of the bottom right-hand graph on that page working.) I tried using a Thickness style for Filling of a non-joined DateListPlot, but it doesn't work because the thickness also applies to the ends of the line -- ie the "rectangle" doesn't actually stop at the axis but goes past it by an amount equal to the value of Thickness. There is also the issue that I will need to combine Line and Bar charts for certain applications. We often plot a year-ended percentage change as a line and then the quarterly or monthly percentage change as small bars on the same axis. Can anyone offer any guidance on placement of ticks in BarChart, and combining them with DateListPlots? Or, failing that, making DateListPlots look like BarCharts? Thanks in advance, Luci
From: Armand Tamzarian on 3 Nov 2009 02:55 On Nov 1, 3:03 am, Luci Ellis <l...(a)verbeia.com> wrote: > Dear MathGroupers, > I am trying to set up some custom functions/ option settings to > replicate the standard look and feel of charts as used by my employer. > These are currently done in DeltaGraph, but I would like to be able to > generate charts directly in Mathematica so that I don't have to worry > about the additional (Export to Excel -> Import into DeltaGraph -> > bother a research assistant ) steps. > > Most of our charts are of time series, and I have been able to > replicate the look for line graphs by customising DateListPlot[]. But I > can't replicate the effect for bar charts. Our standard is to put a > tick every X periods (say, to mark off every year or every quarter) and > then centre the date label in that region. I am having serious problems > putting the ticks in exactly the right place for bar charts. Adding up > bar widths and (prespecified) BarSpacings never quite seems to work. > (If you need an example of what I'm trying to do, have a look at the > two graphs on the left-hand side of the first page inhttp://www.rba.gov.a= u/ChartPack/output_expenditure_activity_fincon.pdf > -- I have the equivalent of the bottom right-hand graph on that page > working.) > > I tried using a Thickness style for Filling of a non-joined > DateListPlot, but it doesn't work because the thickness also applies to > the ends of the line -- ie the "rectangle" doesn't actually stop at the > axis but goes past it by an amount equal to the value of Thickness. > > There is also the issue that I will need to combine Line and Bar charts > for certain applications. We often plot a year-ended percentage change > as a line and then the quarterly or monthly percentage change as small > bars on the same axis. > > Can anyone offer any guidance on placement of ticks in BarChart, and > combining them with DateListPlots? Or, failing that, making > DateListPlots look like BarCharts? > > Thanks in advance, > Luci This requiring some further work but seems to do what you want. Make some sample data ...I guess it might come in this sort of format someData = Flatten[Table[{ToString[i] <> "q" <> ToString[j], RandomReal [{-10, 10}]}, {i, 1999, 2008}, {j, 1, 4}], 1]; You will be able to convert it to this format easily enough: data1 = Flatten[Table[{{i, j}, RandomReal[{-5, 5}]}, {i, 1999, 2008}, {j, 1, 4}], 1]; data2 = Flatten[Table[{{i, j*3}, RandomReal[{8, 20}]}, {i, 1999, 2008}, {j, 1, 4}],1]; (* need to tweek this for leap years *) dates[{year_, quarter_}] := Which[ quarter == 1, DatePlus[{year, 1, 0}, #] & /@ Range[90], quarter == 2, DatePlus[{year, 4, 0}, #] & /@ Range[91], quarter == 3, DatePlus[{year, 7, 0}, #] & /@ Range[92], quarter == 4, DatePlus[{year, 10, 0}, #] & /@ Range[92] ]; barData = Thread[{dates[#[[1]]], #[[2]]}] & /@ data1; p1 = DateListPlot[barData, Joined -> False, Filling -> 0]; p1 = DeleteCases[p1, _Point, \[Infinity]]; p2 = DateListPlot[data2, Joined -> True, PlotStyle -> Thick]; Show[p2, p1, PlotRange -> All] I don't know how to get the year labels centred. Maybe someone else can offer a suggestion. Mike
From: Luci Ellis on 4 Nov 2009 01:34 First, thanks to Armand/Mike for his suggestion. It gets me a long way to what I need. The other suggestions to use add-on products are well-taken, but aren't likely to be accepted by my employer. Thanks anyway. On 2009-11-03 18:55:08 +1100, Armand Tamzarian <mike.honeychurch(a)gmail.com> said: > On Nov 1, 3:03 am, Luci Ellis <l...(a)verbeia.com> wrote: >> >> Can anyone offer any guidance on placement of ticks in BarChart, and >> combining them with DateListPlots? Or, failing that, making >> DateListPlots look like BarCharts? >> >> Thanks in advance, >> Luci > > This requiring some further work but seems to do what you want. > > Make some sample data ...I guess it might come in this sort of format > > someData = Flatten[Table[{ToString[i] <> "q" <> ToString[j], RandomRe= al > [{-10, 10}]}, {i, 1999, 2008}, {j, 1, 4}], 1]; > > You will be able to convert it to this format easily enough: > > data1 = Flatten[Table[{{i, j}, RandomReal[{-5, 5}]}, {i, 1999, 2008}, > {j, 1, 4}], 1]; > data2 = Flatten[Table[{{i, j*3}, RandomReal[{8, 20}]}, {i, 1999, > 2008}, {j, 1, 4}],1]; > > (* need to tweek this for leap years *) Create the daily dates as a flat list, then use GatherBy? > > dates[{year_, quarter_}] := Which[ > quarter == 1, DatePlus[{year, 1, 0}, #] & /@ Range[90], > quarter == 2, DatePlus[{year, 4, 0}, #] & /@ Range[91], > quarter == 3, DatePlus[{year, 7, 0}, #] & /@ Range[92], > quarter == 4, DatePlus[{year, 10, 0}, #] & /@ Range[92] > ]; > > barData = Thread[{dates[#[[1]]], #[[2]]}] & /@ data1; > > p1 = DateListPlot[barData, Joined -> False, Filling -> 0]; > p1 = DeleteCases[p1, _Point, \[Infinity]]; > p2 = DateListPlot[data2, Joined -> True, PlotStyle -> Thick]; > > Show[p2, p1, PlotRange -> All] This is a very helpful clue, thanks. In fact, as long as you are only exporting graphics to PDF, GIF, PNG etc, there is no need to DeleteCases the Points. This works: DateListPlot[{barData1, barData1a}, PlotStyle -> Directive[Opacity[0]], =E2=80=A8 Filling -> {1 -> {0, Blue}, 2 -> {{1}, Red}}] (try this for barData1 = Flatten[Most /@ barData, 1]; and data1a = {0, 1.*Sign[#[[2]]]} + # & /@ data1 barData1a = Flatten[Most /@ (Thread[{dates[#[[1]]], #[[2]]}] & /@ data1a), 1]; ) It's not even necessary to create two plots and use Show. But it is incredibly slow (creating daily data out of non-daily data), and will only work for stacked bars (see below) not side by side bars, unless one fakes the date positions for the second series. i will keep working on it. In the meantime, any other suggestions are greatly appreciated. > I don't know how to get the year labels centred. Maybe someone else > can offer a suggestion. This bit I already have working -- just not TickPlacement in BarChart. It involves AdjustmentBox constructs like this. RBADateTicks[min_, max_, opts___Rule] :==E2=80=A8 Module[{seq},=E2=80=A8= With[{dateformat = DateLabelFormat /. {opts} /. Options[RBADateTicks],=E2= =80=A8 datelabelspacing = DateLabelSpacing /. {opts} /. Options[RBADateTicks],=E2=80=A8 vertshift = DateLabelVerticalShift /= .. {opts} /. Options[RBADateTicks],=E2=80=A8 afac = With[{afacopt = DateLabe= lOffset /. {opts} /. Options[RBADateTicks]},=E2=80=A8 Switch[afacopt, Automati= c, =E2=80=A8 AutoDateLabelOffset[max - min + 1], _?NumericQ, afacopt]]},=E2=80=A8 = seq = If[datelabelspacing == Automatic, AutoDateLabel[max - min + 1], =E2= =80=A8 datelabelspacing];=E2=80=A8 Table[{{i, 1, 1}, =E2=80=A8 If[Mod[max = - i, seq] == 0, =E2=80=A8 DisplayForm[=E2=80=A8 AdjustmentBox[DateString[{i= , 1, 1}, {dateformat}], =E2=80=A8 BoxBaselineShift -> 0.1, BoxMargins -> {{= afac, 0}, {0, 0}}]], =E2=80=A8 ""], {0.015, 0}}, {i, Range[min, max]}]=E2=80= =A8 ]] where AutoDateLabelOffset[num_Integer?Positive] := =E2=80=A8 Switch[num, 1, 3= 2, 2, 16, 3, 10.5,=E2=80=A8 4, 8.,=E2=80=A8 5, 6.8,=E2=80=A8 6, 5.2, 7, 4.7,= 8, 4.0, 9, 3.7, 10, 3.5, 11, 3.25, 12, 2.9, 13, 2.65, 14, =E2=80=A8 2.35, 15, 2.3, 16, 2.15,= 17, 2.05, 18, 2., 19, 1.9, 20, 1.8, _, 1.5] and AutoDateLabel[num_Integer?Positive] := =E2=80=A8 Piecewise[{{1, num < 6= }, {2, 5 <= num <= 10}, {3, 10 < num <= 15}, {4, =E2=80=A8 15 < num < 20}= , {5, 20 <= num <= 45}, {10, num > 45}}, 5]=E2=80=A8
From: Luci Ellis on 5 Nov 2009 04:18 An update: This seems to work nicely in DateListPlot: Epilog -> ({ Blue, =E2=80=A8 Rectangle[Offset[{-.2, 0}, {#[[1]], 0}], Offset[{1.1, 0}, #]] & /@ =E2=80=A8 data]}) (where the data are in the form {{1999,12,1},number}..} ) The exact amount of offset depends on the number of bars, but this is not a big issue. Stacked bars will need MapThread or something, presumably. This solution also renders much faster than Mike's. I hope it is useful to others. Regards, Luci On 2009-11-04 17:34:26 +1100, Luci Ellis <luci(a)verbeia.com> said: > First, thanks to Armand/Mike for his suggestion. It gets me a long way > to what I need. The other suggestions to use add-on products are > well-taken, but aren't likely to be accepted by my employer. Thanks > anyway. > > On 2009-11-03 18:55:08 +1100, Armand Tamzarian > <mike.honeychurch(a)gmail.com> said: > >> On Nov 1, 3:03 am, Luci Ellis <l...(a)verbeia.com> wrote: >>> >>> Can anyone offer any guidance on placement of ticks in BarChart, and >>> combining them with DateListPlots? Or, failing that, making >>> DateListPlots look like BarCharts? >>> >>> Thanks in advance, >>> Luci >> >> This requiring some further work but seems to do what you want. >> >> Make some sample data ...I guess it might come in this sort of format >> >> someData = Flatten[Table[{ToString[i] <> "q" <> ToString[j], RandomReal >> [{-10, 10}]}, {i, 1999, 2008}, {j, 1, 4}], 1]; >> >> You will be able to convert it to this format easily enough: >> >> data1 = Flatten[Table[{{i, j}, RandomReal[{-5, 5}]}, {i, 1999, 2008}, >> {j, 1, 4}], 1]; >> data2 = Flatten[Table[{{i, j*3}, RandomReal[{8, 20}]}, {i, 1999, >> 2008}, {j, 1, 4}],1]; >> >> (* need to tweek this for leap years *) > > Create the daily dates as a flat list, then use GatherBy? > >> >> dates[{year_, quarter_}] := Which[ >> quarter == 1, DatePlus[{year, 1, 0}, #] & /@ Range[90], >> quarter == 2, DatePlus[{year, 4, 0}, #] & /@ Range[91], >> quarter == 3, DatePlus[{year, 7, 0}, #] & /@ Range[92], >> quarter == 4, DatePlus[{year, 10, 0}, #] & /@ Range[92] >> ]; >> >> barData = Thread[{dates[#[[1]]], #[[2]]}] & /@ data1; >> >> p1 = DateListPlot[barData, Joined -> False, Filling -> 0]; >> p1 = DeleteCases[p1, _Point, \[Infinity]]; >> p2 = DateListPlot[data2, Joined -> True, PlotStyle -> Thick]; >> >> Show[p2, p1, PlotRange -> All] > > This is a very helpful clue, thanks. In fact, as long as you are only > exporting graphics to PDF, GIF, PNG etc, there is no need to > DeleteCases the Points. This works: > > DateListPlot[{barData1, barData1a}, PlotStyle -> Directive[Opacity[0]], > =E2=80=A8 Filling -> {1 -> {0, Blue}, 2 -> {{1}, Red}}] > (try this for barData1 = Flatten[Most /@ barData, 1]; and > data1a = {0, 1.*Sign[#[[2]]]} + # & /@ data1 > barData1a = Flatten[Most /@ (Thread[{dates[#[[1]]], #[[2]]}] & /@ > data1a), 1]; ) > > It's not even necessary to create two plots and use Show. > > But it is incredibly slow (creating daily data out of non-daily data), > and will only work for stacked bars (see below) not side by side bars, > unless one fakes the date positions for the second series. > > i will keep working on it. In the meantime, any other suggestions are > greatly appreciated. > >> I don't know how to get the year labels centred. Maybe someone else >> can offer a suggestion. > > This bit I already have working -- just not TickPlacement in BarChart. > It involves AdjustmentBox constructs like this. > > RBADateTicks[min_, max_, opts___Rule] :==E2=80=A8 Module[{seq},= =E2=80=A8= > > With[{dateformat = DateLabelFormat /. {opts} /. Options[RBADateTicks]= ,=E2= > =80=A8 > datelabelspacing = DateLabelSpacing /. {opts} /. > Options[RBADateTicks],=E2=80=A8 vertshift = DateLabelVertica= lShift /= > . {opts} > /. Options[RBADateTicks],=E2=80=A8 afac = With[{afacopt = = DateLabe= > lOffset /. > {opts} /. Options[RBADateTicks]},=E2=80=A8 Switch[afacopt, = Automati= > c, =E2=80=A8 > AutoDateLabelOffset[max - min + 1], _?NumericQ, afacopt]]},=E2== 80=A8 = > seq > = If[datelabelspacing == Automatic, AutoDateLabel[max - min + 1],= =E2= > =80=A8 > datelabelspacing];=E2=80=A8 Table[{{i, 1, 1}, =E2=80=A8 = If[Mod[max = > - i, seq] == > 0, =E2=80=A8 DisplayForm[=E2=80=A8 AdjustmentBox= [DateString[{i= > , 1, 1}, > {dateformat}], =E2=80=A8 BoxBaselineShift -> 0.1, BoxMargi= ns -> {{= > afac, > 0}, {0, 0}}]], =E2=80=A8 ""], {0.015, 0}}, {i, Range[min, ma= x]}]=E2=80= > =A8 ]] > > where > > AutoDateLabelOffset[num_Integer?Positive] := =E2=80=A8 Switch[n= um, 1, 3= > 2, 2, > 16, 3, 10.5,=E2=80=A8 4, 8.,=E2=80=A8 5, 6.8,=E2=80== A8 6, 5.2, 7, 4.7,= > 8, 4.0, 9, 3.7, 10, > 3.5, 11, 3.25, 12, 2.9, 13, 2.65, 14, =E2=80=A8 2.35, 15, 2.3, 1= 6, 2.15,= > 17, > 2.05, 18, 2., 19, 1.9, 20, 1.8, _, 1.5] > > and > > AutoDateLabel[num_Integer?Positive] := =E2=80=A8 Piecewise[{{1,= num < 6= > }, {2, 5 > <= num <= 10}, {3, 10 < num <= 15}, {4, =E2=80=A8 15 < n= um < 20}= > , {5, 20 <= > num <= 45}, {10, num > 45}}, 5]=E2=80=A8
|
Pages: 1 Prev: Version numbesr. Was Re: ToExpression[.., TexForm] Next: Prufer Code/ LabeledTreeToCode Bug? |