7
$\begingroup$

The wonderful error bar log plots package ErrorBarLogPlots from V6 no longer positions labels correctly (since v9 or maybe v8) so I used the same function with Prolog to place a list of labels.

Then in v10 beta PlotRangePadding no longer works either and I can't find a work around for that, so I tried to go back to basics and use the very elegant solution by Belisarius' et.al in:

Plotting Error Bars on a Log Scale

I was able to modify this to make asymmetric $Y$ error bars, then I tried to add $X$-errors and got tied up in knots with the Joined and Filling commands.

The aim is to plot a set of $5$ lists of xy values, {xy, xyP, xyM, xPy, xMy} where P and M refer to the plus and minus error of the $x$ or $y$ value preceding it, with a Filling / Joined statement that joins the first point to the other 4 points.

Ideally the plot symbols should also switch between vertical and horizontal bars for the $x$ and $y$ error points and something else for the $x, y$ point. (I asked Support about including an errorlistlogplot command in Mathematica but I expect it won't make it into v10).

The lines below generate and plot the 5 sets of points. Is there a straightforward combination of Filling / Joined statements to achieve this?

SeedRandom[1234]
dataX = Sort@RandomReal[{0.5, 1}, 10];
dataY = RandomReal[{0.5, 1}, 10];
{errorYP, errorYM, errorXP, errorXM} = RandomReal[.5, {4, 10}];
dataYP = dataY + errorYP;
dataYM = dataY - errorYM;
dataXP = dataX + errorXP;
dataXM = dataX - errorXM;
xy = Transpose[{dataX, dataY}];
xyP = Transpose[{dataX, dataYP}];
xyM = Transpose[{dataX, dataYM}];
xPy = Transpose[{dataXP, dataY}];
xMy = Transpose[{dataXM, dataY}];

ePlot[plotFun_, data_] := plotFun[data, Filling -> Automatic, PlotRange -> All,
                                        Joined -> {False, False, False, False, False}];

ePlot[ListLogPlot, {xy, xyP, xyM, xPy, xMy}]

enter image description here

$\endgroup$
  • $\begingroup$ I suppose you can't ask for solution on V10 since it is not released yet. So you want the solution for nonsymetric errorbars in x and y axis without PlotRangePadding? $\endgroup$ – Kuba Feb 12 '14 at 7:26
  • $\begingroup$ Yes v9. The PlotRangePadding command works in V10 with the inbuilt ListLog plots etc, but not with plots created using the external package ErrorBarLogPlots. So a v9 solution is likely a v10 solution also. $\endgroup$ – DrBubbles Feb 12 '14 at 19:36
6
$\begingroup$

README: This answer is not correct scientifically, I just transformed error bars to log scale instead of doing a correct error propagation. Didn't have time to fix it yet :(


Here's a minimal example:

data = {{20, 100}, {30, 10}, {100, 1000}, {500, 1000}};
xer = {{10, 10}, {20, 300}, {50, 50}, {100, 200}};
yer = {{50, 50}, {5, 50}, {100, 500}, {300, 100}};

errorPlot[#, data, xer, yer] & /@ {ListPlot, ListLogPlot, 
                                   ListLogLogPlot, ListLogLinearPlot};

enter image description here

Code:

errorPlot[plot_, data_, xer_, yer_] := With[{
       tr = Transpose@data,
       arrow = Graphics[{Red, Line[{{0, 1/2}, {0, -1/2}}]}]},
      Module[{PlusMinus, limits, limitsRescaled, dataRescaled, lines, scale},

       scale = plot /. {ListPlot -> {# &, # &}, ListLogPlot -> {# &, Log}, 
                        ListLogLogPlot -> {Log, Log}, ListLogLinearPlot -> {Log, # &}};

       PlusMinus[a_, b_] := {a - b[[1]], a + b[[2]]};
       limits =  MapThread[MapThread[PlusMinus, {#, #2}] &,
                           {tr, {xer, yer}}];

       limitsRescaled = MapThread[Compose, {scale, limits}];   
       dataRescaled = MapThread[Compose, {scale, tr}];

       lines = Flatten[
                MapAt[Reverse, 
                      MapThread[{{#2[[1]], #}, {#2[[2]], #}} &, 
                                {Reverse@dataRescaled, limitsRescaled}, 2], 
                      {2, ;; , ;;}], 1];   

        Show[
         plot[data, PlotStyle -> AbsolutePointSize@7, Axes -> False, Frame -> True, 
                    BaseStyle -> 18, ImageSize -> 500],
         Graphics[{Arrowheads[{{-.02, 0, arrow}, {.02, 1, arrow}}], Thick, Arrow[lines]}]
         ,
         PlotRange -> ({Min[#], Max[#]} & /@ Transpose@Flatten[lines, 1])]]]
$\endgroup$
  • $\begingroup$ This works great with Show[errorPlot[ListLogPlot,data[[#]],xer[[#]],yer[[#]]]&/@Range[Length[data]] for plotting multiple series on the same plot. To apply different formatting for each series we can pass a list of #'d formatting options. I wasn't able to figure out how to arrange the 'data' and err lists to pass multiple data sets in one command (multiple series on one plot without Show); some form of Transpose[data,{?,?}], and Transpose[xer,{?,?}]. Would that be more efficient than using Show to get multiple series on one plot? Great solution either way. $\endgroup$ – DrBubbles Feb 12 '14 at 19:32
  • $\begingroup$ @DrBubbles I'll try to make it more usefull. I will tell you when I'm done ;) $\endgroup$ – Kuba Feb 12 '14 at 20:00
  • $\begingroup$ I moved the arrow heads inside the plot command to add multiple data sets with Tooltips: Show[plot[Tooltip[data[[#]], ttips[[#]]] & /@ Range[Length[data]], PlotStyle -> AbsolutePointSize@7, Axes -> False, Frame -> True, BaseStyle -> 18, ImageSize -> 500, Prolog -> {Arrowheads[{{-.02, 0, arrow}, {.02, 1, arrow}}], Thick, Arrow[lines]}], PlotRange -> ({Min[#], Max[#]} & /@ Transpose@Flatten[lines, 1])] and called the function with errorPlot[plot_, data_, xer_, yer_, ttips_] and multiple data sets. Show overplots the multiple series with tooltips but only one set of error bars. $\endgroup$ – DrBubbles Feb 12 '14 at 21:45
  • $\begingroup$ Sorry, I can't format the comments properly. $\endgroup$ – DrBubbles Feb 12 '14 at 21:49
  • $\begingroup$ @Kuba It would be great if the code could be modified to accommodate also without x axis error bars case. $\endgroup$ – Al Guy Sep 3 '16 at 3:25

protected by Kuba Nov 29 '18 at 11:40

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.