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$
2
  • $\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
    Commented Feb 12, 2014 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
    Commented Feb 12, 2014 at 19:36

1 Answer 1

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$
6
  • $\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
    Commented Feb 12, 2014 at 19:32
  • $\begingroup$ @DrBubbles I'll try to make it more usefull. I will tell you when I'm done ;) $\endgroup$
    – Kuba
    Commented Feb 12, 2014 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
    Commented Feb 12, 2014 at 21:45
  • $\begingroup$ Sorry, I can't format the comments properly. $\endgroup$
    – DrBubbles
    Commented Feb 12, 2014 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
    Commented Sep 3, 2016 at 3:25

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