3
$\begingroup$

the data is

Needs["ErrorBarPlots`"];

data={{{{-1.04845, -1.16241}, ErrorBar[0.0001]}, {{-1.06996, -1.16277}, 
   ErrorBar[0.00006]}, {{-1.00061, -1.16337}, 
   ErrorBar[0.00006]}, {{-1.19685, -1.16283}, 
   ErrorBar[0.00008]}, {{-1.1696, -1.16354}, 
   ErrorBar[0.00005]}, {{-1.01451, -1.16399}, 
   ErrorBar[0.00006]}}, {{{-0.49151, -1.16241}, 
   ErrorBar[0.0001]}, {{-0.45521, -1.16277}, 
   ErrorBar[0.00006]}, {{-0.39356, -1.16337}, 
   ErrorBar[0.00006]}, {{-0.39785, -1.16283}, 
   ErrorBar[0.00008]}, {{-0.35805, -1.16354}, 
   ErrorBar[0.00005]}, {{-0.34185, -1.16399}, ErrorBar[0.00006]}}}

And I plot it with

ErrorListPlot[data,
  Frame -> True, PlotMarkers -> {Automatic}, Joined -> True, 
 Mesh -> All, PlotRange -> All]

which gives

enter image description here

I want to add arrow in the middle of each line of this plot to show the evolution of data like below

enter image description here

What is the best way to do this?

$\endgroup$
4
$\begingroup$

I usually modify plots using the following methods. It's rarely automated, but it works. The plan is to replace the Lines in the Graphics object represented by the figure with Arrows, but we need to find them first.

First, we use the data in the OP and name the function plt:

plt = ErrorListPlot[data,
       Frame -> True, PlotMarkers -> {Automatic},
       Joined -> True, Mesh -> All, PlotRange -> All];

Then, we want to extract from the plot all Graphics primitives that are Lines using

Cases[Normal[plt], _Line, Infinity]

The first three elements of this list are

{Line[{{-1.04845, -1.16241}, {-1.06996, -1.16277}, {-1.00061, -1.16337}, {-1.19685, -1.16283}, {-1.1696, -1.16354}, {-1.01451, -1.16399}}],
 Line[{{-1.04845, -1.16231}, {-1.04845, -1.16251}}], 
 Line[{Offset[{1.5, 0}, {-1.04845, -1.16231}],
 ... }

The first element is the Line joining the points (and there is another one later on). The second element is the vertical error bar, and the third is one of either the top or lower horizontal bars in the error bar. We only want to extract the Lines joining the points, so we do

Cases[Normal[plt], Line[a_?(FreeQ[#, Offset] &)] /; Length[a] > 2, Infinity]
(* {Line[{{-1.04845, -1.16241}, {-1.06996, -1.16277}, {-1.00061, -1.16337}, {-1.19685, -1.16283}, {-1.1696, -1.16354}, {-1.01451, -1.16399}}],
    Line[{{-0.49151, -1.16241}, {-0.45521, -1.16277}, {-0.39356, -1.16337}, {-0.39785, -1.16283}, {-0.35805, -1.16354}, {-0.34185, -1.16399}}]} *)

That's them! So we modify the plot as follows:

plt
  /. Line[a_?(FreeQ[#, Offset] &)] /; Length[a] > 2
      :> {Arrowheads[{{0.05, 0.5}}], Arrow /@ Partition[a, 2, 1]}

resulting in

enter image description here

$\endgroup$
  • $\begingroup$ Hi, march. Thank you very much for your answer. I learned a lot of clever tricks from your answer. One thing I don't understand is Normal. I never thought Normal could apply to a plot ! It seems that this is not documented and I still haven't figured out what exactly has Normal done to a plot. for example, I found Cases[plt, Line[a_?(FreeQ[#, Offset] &)] /; Length[a] > 2, Infinity] only got {Line[{1, 2, 3, 4, 5, 6}], Line[{7, 8, 9, 10, 11, 12}]} $\endgroup$ – matheorem Jul 13 '16 at 6:39
  • $\begingroup$ @matheorem, Normal[] converts GraphicsComplex[] objects (which are usually produced by plotting functions) into an explicit list of primitives and directives. You can search the site for many examples of its use. $\endgroup$ – J. M. is away Jul 13 '16 at 6:41
  • $\begingroup$ @J.M. Hi, J.M. That is still not clear. Why Normal[plt] deletes the errorbar? $\endgroup$ – matheorem Jul 13 '16 at 6:43
  • $\begingroup$ You can answer that yourself, @matheorem. Ponder on the result of FreeQ[ErrorListPlot[(* stuff *)], _ErrorBar]. $\endgroup$ – J. M. is away Jul 13 '16 at 6:46
  • $\begingroup$ @J.M. Nope. The plt is free from ErrorBar head already, the errorbar is drawn by Line. What I mean is that why Normal[plt] output a plot without a errorbar line? You said "Normal[] converts GraphicsComplex[] objects", but you didn't mean it will change the plot, right? $\endgroup$ – matheorem Jul 13 '16 at 6:55
3
$\begingroup$
llp = ListLinePlot[data[[All, All, 1]], Frame -> True, 
    PlotStyle -> Arrowheads[{0, .025, 0}], PlotRange -> All] /.
   Line[x_] :> (Arrow@Partition[x, 2, 1]);

elp = ErrorListPlot[data, PlotMarkers -> {Automatic}, Joined -> False];

Show[llp, elp]

Mathematica graphics

$\endgroup$
  • $\begingroup$ Oh, using Show! Clever trick. Upvoted : ) $\endgroup$ – matheorem Jul 15 '16 at 2:04
  • $\begingroup$ I never thought Arrowheads could be put into PlotStyle, it is undocumented, right? $\endgroup$ – matheorem Jul 15 '16 at 2:07
  • $\begingroup$ @matheorem, thank you for the vote. Since Arrowheads is a graphics directive, it can be used in PlotStyle. There is an example in the documentation: Arrow >> Properties & Relations $\endgroup$ – kglr Jul 15 '16 at 2:16
  • $\begingroup$ Thank you, kglr. It is just too many things can put into "Style", I never succeeded in figuring them out clearly. : ) $\endgroup$ – matheorem Jul 15 '16 at 2:31

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.