34
fun[p_] :=
 Module[{per, bd, dd},
  per = Interpreter["Person"][p];
  bd = DateValue[PersonData[per, "BirthDate"], "Year"];
  dd = DateValue[PersonData[per, "DeathDate"], "Year"];
  Range[bd, dd]]

names = 
 {"Napoleon Bonaparte", "Jane Austen", "Hegel", "Marx", "Gauss", "Madame de Stael", "Lenin"};

res = fun /@ names;
par = Partition[#, 2] & /@ Table[Riffle[res[[n]], n] ~ Join ~ {n}, {n, 1, Length @ res}];

ListLinePlot[par,
 ColorFunction -> "Rainbow",
 Ticks -> {Range[1750, 1980, 10], Automatic},
 GridLines -> {Range[1750, 1920, 10], None},
 PlotLegends -> 
  SwatchLegend["Rainbow", names, LegendLayout -> "ReversedColumn", LegendMarkerSize -> {{10, 10}}],
 PlotStyle -> Thickness[0.02],
 ImageSize -> 600]

enter image description here

How can I align the legend to their lifespan bars?

eldo
  • 67,911
  • 5
  • 60
  • 168

2 Answers2

44

Use the individual legends as tick labels:

dates = Through[{First, Last}@#] & /@ res

{{1769, 1821}, {1775, 1817}, {1770, 1831}, {1818, 1883}, {1777, 1855}, {1766, 1817}, {1870, 1924}}

llpd = MapIndexed[Thread@{#, First@#2} &, dates];

legends = MapIndexed[SwatchLegend[{ColorData[{"Rainbow", {1, 7}}][## & @@ #2]}, {#}, LegendMarkerSize -> {{10, 10}}] &, names];

ListLinePlot[llpd, Joined -> True, ColorFunction -> "Rainbow", Frame -> True, FrameTicks -> {{None,Thread[{Range[7], legends}]}, {Range[1750, 1930,20], Automatic}}, GridLines -> {Range[1750, 1920, 10], None}, AxesOrigin -> {1750, 0}, PlotRange -> {{1750, 1930}, {0, 8}}, PlotStyle -> Directive[Thickness[0.05], CapForm["Butt"]], ImageSize -> 600]

enter image description here

Label the bars with names:

ListPlot[llpd, Joined -> True, ColorFunction -> "Rainbow",
  Frame -> True,
  FrameTicks -> {{None, None}, {Range[1750, 1930,20], Automatic}},
  GridLines -> {Range[1750, 1920, 10], None},
  Epilog -> (Text[Style[#2, 12, Bold], Mean@#1] & @@@ Transpose[{llpd, names}]),
  AxesOrigin -> {1750, 0}, PlotRange -> {{1750, 1930}, {0, 8}},
  PlotStyle -> Directive[Thickness[0.05], CapForm["Butt"]], ImageSize -> 600]

enter image description here

Use the option PlotLabels

In versions 10.4+, we can also use the option PlotLabels:

ListLinePlot[llpd, Joined -> True, 
 PlotLabels -> legends, 
 ColorFunction -> "Rainbow", Frame -> True, 
 GridLines -> {Range[1750, 1920, 10], None}, AxesOrigin -> {1750, 0}, 
 PlotRange -> {{1750, 1930}, {0, 8}}, 
 PlotStyle -> Directive[Thickness[0.05], CapForm["Butt"]], ImageSize -> 600]

enter image description here

To remove the callout curves, use

% /. _BSplineCurve -> {}

enter image description here

kglr
  • 394,356
  • 18
  • 477
  • 896
11

Borrowing from kguler the legends

    legends = 
 MapIndexed[
  SwatchLegend[{ColorData[{"Rainbow", {1, 7}}][## & @@ #2]}, {#}, 
    LegendMarkerSize -> {{10, 10}}] &, names]; 
p1 = 
 ListLinePlot[par, ColorFunction -> "Rainbow", 
  Ticks -> {Range[1750, 1980, 10], Automatic}, 
  PlotRangePadding -> {{5, 50}, {0, 1}}, 
  GridLines -> {Range[1750, 1920, 10], None}, 
  PlotStyle -> Thickness[0.02], ImageSize -> 600];
 p2 = 
 Graphics[Inset[
     legends[[#]], {1940 + StringLength[names[[#]]], #}] & /@ 
   Range[7]]; Show[p1, p2]

enter image description here

Basheer Algohi
  • 19,917
  • 1
  • 31
  • 78