# Plot with two scales for X axis

I want to do something similar to 1 Plot, 2 Scale/Axis but for the X-axis.

The aim is to have physical units below, but array indices at the top for easy access to the discrete data range.

So far I tried:

XY = Table[{i, Sin[i]}, {i, -10, 10, 0.5}];

DoubleXAxisPlotExample[XY : {{_?NumberQ, _?NumberQ} ..}] :=
Overlay[{
ListLinePlot[XY,
Frame -> True,
FrameTicks -> {{All, None}, {All, None}},
PlotRange -> All],
ListLinePlot[Transpose[{Range[Length[XY]], Part[XY, All, 2]}],
Frame -> True,
FrameTicks -> {{All, None}, {None, All}},
PlotRange -> All]
}];


DoubleXAxisPlotExample@XY returns: However, with:

XY = Table[{i, 100000*Sin[i]}, {i, -10, 10, 0.5}];


DoubleXAxisPlotExample@XY returns: -> the left ticks have been truncated

I understand that ImagePadding -> 25 is there to let enough arbitrary space on the left, however in my code this is a fixed absolute value. To solve the problem, I think that this value should be computed according to the actual plot Y-range, but I do not know how to do that.

Any idea?

You can use my function GraphicsInformation to obtain this information (I think GraphicsInformation is more reliable than Image + BorderDimensions). Install the paclet/function:

PacletInstall[
"GraphicsInformation",
"Site"->"http://raw.githubusercontent.com/carlwoll/GraphicsInformation/master"
];


<<GraphicsInformation


plots = {
ListLinePlot[
XY,
Frame -> True,
FrameTicks -> {{All, None}, {All, None}},
PlotRange -> All
],
ListLinePlot[Transpose[{Range[Length[XY]], Part[XY, All, 2]}],
Frame -> True,
FrameTicks -> {{All, None}, {None, All}},
PlotRange -> All
]
};


{{{44., 1.5}, {17., 0.5}}, {{44., 1.5}, {1.5, 16.}}}

This gives the actual ImagePadding used in the two plots. You can use MapThread to come up with the total ImagePadding that is needed:

MapThread[Max, padding, 2]


{{44., 1.5}, {17., 16.}}

I will leave it to you to include GraphicsInformation in your DoubleXAxisPlotExample function.

• Thanks for this! Happy to see that I was not the only one to have problems with image padding! :) – Picaud Vincent Dec 14 '17 at 17:44

One can automate the image padding with a hack described here and built upon here.

padding[g_Graphics] := With[{im = Image[Show[g, LabelStyle -> White, Background -> White]]}, BorderDimensions[im]]
maxPadding[graphicsSequence__Graphics] := 1 + {Max /@ Transpose@(First /@ #), Max /@ Transpose@(Last /@ #)} &@(padding /@ List@graphicsSequence)


Then,

DoubleXAxisPlotExample[XY : {{_?NumberQ, _?NumberQ} ..}] := Module[{plt1, plt2, pad},
plt1 = ListLinePlot[XY,
PlotRange -> All,
Frame -> True, FrameTicks -> {{All, None}, {All, None}}];
plt2 = ListLinePlot[Transpose[{Range[Length[XY]], Part[XY, All, 2]}],
PlotRange -> All,
Frame -> True, FrameTicks -> {{All, None}, {None, All}}];
plt = Overlay[{

XY = Table[{i, 100000*Sin[i]}, {i, -10, 10, 0.5}];
` 