2
$\begingroup$

ListPlot has the option to label points using Labeled or Callout. At least those are the two ways to do it of which I am aware of. A simple example:

ListPlot[{Labeled[{1, 2}, "(1,2)"], Callout[{2, 1}, "(2,1)"]}, PlotRange -> {{0, 2.5}, {0, 2.5}}]

enter image description here

Now two questions:

  1. How can I add two labels to one point? Each label should thereby be (roughly) opposite to its counter. Drawing the same plot twice as a workaround doesn't work. It would recognise the points as being too dense to display their labels.

  2. Is there a way to have precise control over the label positions in terms of ocation angle and distance from the point? The option I know of is to specify Callout[point,label,location], where location could be Above,Below,Before,After,Left,Right, or a pair thereof, such as {Above,Right}. But the latter seems bugged, and I would also appreciate a tighter control than just a grid with 45° angular resolution.

Here a graphical description of what I would like to do. I cannot add the code for this plot, because the curve in it is numerical.

enter image description here

Thanks for suggestions!

$\endgroup$
2
$\begingroup$
SeedRandom[1]
points = RandomPoint[Circle[{0, 0}, {2, 3}], 10];
centroid = RegionCentroid@BoundingRegion[points, "FastDisk"];

labels1 = IntegerName /@ Range[Length@points];
labels2 = IntegerName[#, "French"] & /@ Range[Length@points];

gap = .2;

labeleddata = Table[MapThread[Callout[#, #2, # + i[[1]] gap Normalize[# - centroid], 
        Appearance -> "Leader"] &]@{points, i[[2]]},
     {i, {{-1, labels1}, {1, labels2}}}];

ListPlot[labeleddata, 
  LabelStyle -> 16,
  PlotStyle -> Directive[Red, PointSize[Large]], 
  AspectRatio -> 3/2, 
  PlotRangeClipping -> False, 
  ImagePadding -> 60, ImageSize -> 600, 
  PlotRange -> {{-2, 2}, {-3, 3}}, 
  Prolog -> Circle[{0, 0}, {2, 3}]]

enter image description here

$\endgroup$
1
  • $\begingroup$ Great, thank you so much! $\endgroup$ – Britzel Jul 27 '20 at 15:54
1
$\begingroup$

You can nest Labeled and Callout individually or together. They can be individually positioned.

ListPlot[{Callout[Labeled[{1, 2}, "Label 1", Above], "Label 2", Below,
    Appearance -> None],
  Labeled[Callout[{2, 1}, "Label 1", Above, Appearance -> None], 
   "Label 2", Below],
  Labeled[Labeled[{.5, .5}, "Label 1", Above], "Label 2", Below],
  Callout[Callout[{1, 1}, "Label 1", Above, Appearance -> None], 
   "Label 2", Below, Appearance -> None]},
 PlotRange -> {{0, 2.5}, {0, 2.5}}]

enter image description here

You can also use Show to overlap two plots using either Labeled or Callout

Show[
 ListPlot[{
   Labeled[{1, 2}, "Label 1", Above],
   Callout[{2, 1}, "Label 1", Above]},
  PlotRange -> {{0, 2.5}, {0, 2.5}}],
 ListPlot[{
   Labeled[{1, 2}, "Label 2", Below],
   Callout[{2, 1}, "Label 2", Below]},
  PlotRange -> {{0, 2.5}, {0, 2.5}}]]

enter image description here

For more precise positioning you can use Text in an Epilog

ListPlot[{{1, 2}, {2, 1}},
 PlotRange -> {{0, 2.5}, {0, 2.5}},
 Epilog -> {
   Text["Label 1", {1, 2}, {1.5, 1.25}],
   Text["Label 2", {1, 2}, {-1.5, -1.25}],
   Text["Label 1", {2, 1}, {1.5, -1.25}],
   Text["Label 2", {2, 1}, {-1.5, 1.25}]}]

enter image description here

$\endgroup$
1
  • $\begingroup$ @ Bob Hanlon Thank you so much! I suppose this would qualify as solution as well. However I ended up marking kglr's solution as such, since it is more directly what I was looking for. $\endgroup$ – Britzel Jul 27 '20 at 15:55

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.