# Plotting vertical lines without changing plot range with TwoAxisListLinePlot

I want to plot vertical lines given by some equation in my code below. I want this vertical line to touch x-axis with years and the axis directly above it which closes the graph at a point x=year specified by the equation. My problem is that whenever I change the y value on the line to get line that touches the base of x-axis and the axis above it the PlotRange of left and right axes change and my line doesn't "close the plot".

The question may be frased differently: How to plot vertical line that touches x-axis(the one with years) at some specified point x=year and the axis above it, therefore closing the graph ?

Let me say that I tried GridLines but somehow they don't show up if I use TwoAxisListLinePlot. Edit: The code should be extensible to more lines that one.

  TwoAxisListLinePlot[{f_, g_}, plotopts : OptionsPattern[]] :=
Module[{fgraph, ggraph, frange, grange, fticks,
gticks}, {fgraph, ggraph} =
MapIndexed[
ListPlot[#, Joined -> True,
FrameTicksStyle -> Directive[Thickness[0.003], Black, 12],
TicksStyle -> Directive[Thickness[0.003], Black, 12],
Axes -> True, PlotRange -> All,
PlotStyle -> ColorData[1][#2[[1]]]] &, {f, g}]; {frange,
grange} =
Last[PlotRange /. AbsoluteOptions[#, PlotRange]] & /@ {fgraph,
ggraph};
fticks =
Last[Ticks /.
AbsoluteOptions[fgraph,
Ticks]] /. _RGBColor | _GrayLevel | _Hue :> ColorData[1][1] ;
gticks = (MapAt[Function[r, Rescale[r, grange, frange]], #, {1}] & /@
Last[Ticks /.
AbsoluteOptions[ggraph,
Ticks]]) /. _RGBColor | _GrayLevel | _Hue -> ColorData[1][2];
Show[fgraph,
ggraph /.
Graphics[graph_, s___] :>
Graphics[
GeometricTransformation[graph,
RescalingTransform[{{0, 1}, grange}, {{0, 1}, frange}]], s],
Axes -> False, Frame -> True,
FrameStyle -> {ColorData[1] /@ {1, 2}, {Automatic, Automatic}},
FrameTicks -> {{fticks, gticks}, {Automatic, Automatic}},
Evaluate[FilterRules[{plotopts}, Options[ListLinePlot]]]]]

pareto1 = {{2000, 1.254221127}, {2001, 1.347243255}, {2002,
1.38218106}, {2003, 1.313844733}, {2004, 1.3734142182}, {2005,
1.298813854}, {2006, 1.253782028}, {2007, 1.2306716}, {2008,
1.3409995784}, {2009, 1.21464622}, {2010, 1.1720606}, {2011,
1.24292400036}, {2012, 1.19382731433}, {2013,
1.22420356414}, {2014, 1.2223526}, {2015, 1.307600821757}};
pareto2 = {{1995, 1.677402}, {1999, 1.7299}, {1998, 1.8988961}, {1997,
1.8543884}, {2006, 3.2155496200}, {2007, 2.242218}, {2008,
3.892772}, {2009, 2.937621}, {2010, 2.055810}, {2012,
2.03939198}, {2014, 1.76645}, {2015, 1.661591900}, {2013, 1.7859}}

c2002 = Normal@
ContourPlot[x == 2002, {x, 1995, 2015}, {y, 1, 1.43},
ContourStyle -> {Black, Thickness[0.0015], Dashed}];
ab = TwoAxisListLinePlot[{pareto1, pareto2},
Joined -> True, {Frame -> True, PlotLabel -> "", PlotRange -> All,
Joined -> True, PlotMarkers -> {Automatic, Small},
ImageSize -> Large, FrameLabel -> {{"a", "b"}, {"c", ""}},
BaseStyle -> {FontSize -> 14}},
LabelStyle -> Directive[Black, Bold],
FrameTicksStyle -> Directive[Thickness[0.003], Black, 12],
FrameStyle -> Directive[Thickness[0.002], Black, 12],
PlotRange -> {0, 6}];
Show[ab, c2002]

• Show[ab, Epilog -> Cases[c2002, {___, _Line}, Infinity]] Commented Feb 20, 2017 at 20:57
• It works, can you make it an answer? Commented Feb 20, 2017 at 21:00
• By the way, when I try to add a second line it doesn't work. Can I somehow extend your method? Commented Feb 20, 2017 at 21:02
• see the revised version below Commented Feb 20, 2017 at 21:09

In this case, when you combine the two plots, it seems to take the plot range from the second plot rather than the first. One way to fix this is to use the Graphics primitives from the contour plot as an Epilog for the first.

Look at the InputForm of the contour plot:

Short@InputForm@c2002
(* Graphics[{{{}, {}, Tooltip[{Directive[<<4>>], Line[<<1>>]}, <<1>>]}}, {<<11>>}] *)


It's just a Graphics object. We need to just get whatever is the first argument of that Graphics to use as our Epilog,

First@Apply[List]@c2002//Short
(* {{{},{},{Directive[AbsoluteThickness[1.6],,<<9>>[<<7>>],Dashing[{Small,Small}]],<<1>>}}} *)

Show[ab, Epilog -> First@Apply[List]@c2002]


This works no matter how many lines you had in your ContourPlot,

c200206 =
Normal@ContourPlot[{x == 2002, x == 2006}, {x, 1995, 2015}, {y, 1,
1.43}, ContourStyle -> {{Black, Thickness[0.0015], Dashed}, {Red,
Thickness[0.0015], Dashed}}];
Show[ab, Epilog -> First@Apply[List]@c200206]


As an aside, there are much easier ways to get a vertical line than using ContourPlot,

Show[ab, Epilog -> {Thick, Dashed, Red, Line[{{2002, 1}, {2002, 2}}]}]