# Align y-Axes in Overlay plot

I learned about how to plot two datasets in a single plot with two y-axes by using Overlay as has been done in one of the answers in this question.

Now, my datasets are not just positive but the second one also has negative y-values. As a consequence, the origins of the y-axes are now misaligned in the final plot (they are not at the same height).

Is it possible to use this method but align the origins of the different y-axes correspondingly?

I tried to use AxesOrigin but it doesn't seem to work.

Minimal working example to illustrate my problem

plot1 = ListLinePlot[Accumulate[RandomReal[{0, 1}, {100}]],
PlotStyle -> Blue, ImagePadding -> 30,
Frame -> {True, True, True, False},
FrameStyle -> {Automatic, Blue, Automatic, Automatic}];
plot2 = ListLinePlot[RandomReal[{-5, 40}, {100}], PlotStyle -> Red,
ImagePadding -> 30, Axes -> False,
Frame -> {False, False, False, True},
FrameTicks -> {{None, All}, {None, None}},
FrameStyle -> {Automatic, Automatic, Automatic, Red}];
Overlay[{plot1, plot2}]


Reading out the PlotRange might be a way.

• For an user with your reputation, you should know by now to include a minimal working example that shows your code and problem. Please edit your question to improve it. It's never too late to get you Informed badge by taking the tour and learning about good questions. – rhermans Jul 17 '19 at 12:36
• You are right. I apologise for my sloppiness. I just edited my OP. – Display Name Jul 17 '19 at 13:00

Not a complete answer, but some thought for you to start. If I undetstood you correctly, you want to align "zero" ticks of both axes. If so, you need to Show both plots with the same vertical range, and then Overlay new plots.

One can get PlotRanges by pr1=PlotRange[plot1] (and similarly for plot2). You also need PlotRangePadding with the command pad=Options[plot1,PlotRangePadding]. Next you compute common PlotRange by smth like cpr=MinMax[Join[pr1[[2]], pr2[[2]]]]. Now you are ready to replot both polts with this new cpr: newplot1=Show[plot1,PlotRange->cpr,PlotRangePadding->pad] and the like for the plot2. And finally Overlay[{newplot1,newplot2}].

You also may use undocumented command

Chartingget2DPlotRange[plot1]


This will give you "whole" PlotRange including PlotRangePadding. in this case in newplot1 you should use PlotRangePadding->None because it is already included in plotrange.

EDIT

Another idea. First you get "whole" PlotRange. Then you need to find such range (for the left axis, e.g.), so that after rescaling its zero becomes zero on the right axis:

Solve[Rescale[0,{x,pr1[[2,2]]},pr2[[2]]]==0,x]


Now you Show[plot1, PlotRange->{x,pr1[[2,2]]},PlotRangePadding->None], then Overlay[...].

• You correctly understood my intention. However, in the actual example the ranges of the different y-axes are quite different (different regimes in terms of magnitudes). The problem is that one then also has to rescale one of the axes I'm afraid. It is a pity that this whole task is so tedious with MMA. Thanks for your answer anyway. – Display Name Jul 17 '19 at 14:18
• Great that works perfectly well. Thank you for the help :) – Display Name Jul 17 '19 at 18:18

An alternative approach based on (1) Rescaleing the second data set to the range of first data set so that the two data sets are aligned at the desired point, (2) Using ChartingFindTicks to find the appropriate frame ticks for the right axis.

We need a simple helper function to find the second argument for Rescale:

ClearAll[modifiedrange]
modifiedrange[{{a_, b_}, {c_, d_}}, z_: 0] /; z <= d := {(a d - (a - b + d) z)/(b - z), d}


Examples:

SeedRandom[1]
data1 = Accumulate[RandomReal[{0, 1}, {100}]];
data2 = RandomReal[{-5, 40}, {100}];

ao = {0, 0};
data2b = Rescale[data2, modifiedrange[MinMax /@ {data1, data2}, ao[[2]]], MinMax @ data1]
tickF = ChartingFindTicks[MinMax@data1, modifiedrange[MinMax/@{data1, data2}, ao[[2]]]];

ListLinePlot[{data1, data2b},
PlotStyle -> {Blue, Red}, Frame -> True,
FrameStyle -> {{Blue, Red}, {Automatic, Automatic}},
FrameTicks -> {{Automatic, tickF}, {Automatic, Automatic}},
AxesOrigin -> ao]


Use ao = {0, 10} to align the left and right axes at 10`:

• Thank you for your answer! – Display Name Jul 19 '19 at 8:49