2
$\begingroup$

Below is a plot I made in MATLAB.

MATLAB Error Bar Plot

I need to recreate the above plot in Mathematica. This is what I'm able to achieve on Mathematica 12.2 (the slight formatting differences compared to the MATLAB plot are intentional):

Mathematica Error Bar Plot

As we can see, the plot in Mathematica has a non-zero "fence width" on top of each plot marker whereas the plot made in MATLAB does not. Is there any way to achieve error bars as shown in the MATLAB plot using Mathematica?

If we assume the x-coordinates are stored in xData, the y-coordinates in yData, and the tops of the error bars in yMaxData (all vectors of the same length), the code I use in Mathematica to generate this plot (ignoring all the formatting) is:

linePlotData1 = Table[{xData[[ii, 1]], Around[yData[[ii, jj]], {0, yMaxData[[ii, jj]]}]}, {jj, 1, numCols}, {ii, 1, numRows}];

where numCols is 2 in this case and numRows is 10 (the length of the data vectors).

To generate the plot, I use ListPlot[linePlotData1] with ScalingFunctions set to {"Log", "Log"} and various other formatting-related commands including IntervalMarkersStyle to format the thickness and color of the error bars. However, I wasn't able to find any documentation regarding whether or not I can format the positive and negative directions of the error bars differently.

Is there a way to do this, preferably without having to use any external packages?

For example, can I set IntervalMarkers to "Bars" for the negative and "Fences" for the positive directions, respectively? The documentation doesn't seem to have any information on whether or not doing so is possible. I tried something like IntervalMarkers -> {{"Bars","Fences"},{"Bars","Fences"}} (repeated twice for each of the two data "columns"), but this threw an error.

Thanks!

$\endgroup$
3
  • 1
    $\begingroup$ does ListPlot[data]/. Line[pat:{{_List,_Offset}..}]:>Line[pat[[;;2]]] give what you need? $\endgroup$ – kglr Apr 21 at 4:54
  • $\begingroup$ @kglr Yes! That's perfect! Thanks so much! I'll admit that I don't quite understand the code (i.e., why it works). So if you have the time and wouldn't mind explaining further (even in the form of an answer if you think it would be useful to the community), that would be very helpful. I'd of course readily accept your answer should you choose to write one. :) $\endgroup$ – Rahul Apr 21 at 5:00
  • $\begingroup$ Rahul, posted the comment as an answer with some explanation of how/why it works. $\endgroup$ – kglr Apr 21 at 5:19
3
$\begingroup$
data = {{1, Around[5, 2]}, {2, Around[4, 1]}, {3, Around[5, 1]}};

lp = ListPlot[data, IntervalMarkersStyle -> Thick]

enter image description here

If we inspect the Line primitives in lp

Cases[lp, _Line, All] // Column 

enter image description here

we find that the fences for a data point are implemented as a Line object with 4 pieces using Offset coordinates (the first two pieces are the top fence and the last two pieces are the bottom fence.) So we can post-process lp to remove the bottom fences (that is, take the first two pieces of the Line object) to get the desired look:

lp /. Line[pat : {{_List, _Offset} ..}] :> Line[pat[[;; 2]]]

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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