# How to add second, linearly rescaled X-axis on the top frame?

From data test, I want to plot a graph with two x axes (see the image which I have added). Two $x$ axes, one at bottom and other on top. In test data, test[[1 ;; All, 1]] is $x$-axis at bottom, test[[1 ;; All, 2]] is $y$-axis and test[[1 ;; All, 3]] is $x$-axis at top. With my code, second $x$-axis on top is not coming properly.

test={{0.875, 0.000361069, -0.137}, {0.9, -0.000429778, -0.1096},
{0.925, -0.000102596, -0.0822}, {0.95, -0.000234415, -0.0548},
{0.975, -0.00066855, -0.0274},{1., -0.00114038, 0}, {1.025,   0.00278551, 0.0274},
{1.05, -0.00148313, 0.0548},{1.075,  0.00132836, 0.0822},
{1.1, -0.000164138, 0.1096}, {1.125, -0.00036032, 0.137}}
top = test[[All, {1, 3}]]
ListLinePlot[Transpose[{test[[1 ;; All, 1]], test[[1 ;; All, 2]]}], Frame-> True,
FrameTicks -> {{Automatic, Automatic}, {Automatic, top}},
PlotRange -> All]


As you can see, the manually specified ticks look awful with their overlapping digits. How could I make them look like the built-in tickmarks, but with a different range?

• I don't quite understand you, but maybe you want FrameTicks -> {{All, None}, {All, All}}? – Alan Jan 21 '17 at 14:15
• I want to plot a graph with two x axes (see the image which I have added). Two x axes, one at bottom and other on top. In test data, test[[1 ;; All, 1]] is x axis at bottom, test[[1 ;; All, 2]] is y axis and test[[1 ;; All, 3]] is x axis at top. – RGG Jan 21 '17 at 14:56
• You need to generate custom FrameTicks manually or use something like: (94726) – Kuba Jan 21 '17 at 15:03
• I don't understand the question. The code you provide already does what you say you want it to do. What else do you need? – Emilio Pisanty Jan 21 '17 at 15:16
• With this code, I do not get x axis on top properly. – RGG Jan 21 '17 at 15:22

The method I originally proposed in a comment does not work in version 9, so here is a method that does.

The usage of the ChartingFindTicks function should be clear from this example,

oldXRange = {Min@#, Max@#} & @ test[[All, 1]]
newXRange = {Min@#, Max@#} & @ test[[All, 3]]
(* {0.875, 1.125} *)
(* {-0.137, 0.137} *)

ListLinePlot[test[[All, ;; 2]], Frame -> True,
FrameTicks -> {
{Automatic, Automatic},
{Automatic, ChartingFindTicks[oldXRange, newXRange]}}]


• -Thank you very much. It is working well with Mathematica 9. – RGG Jan 22 '17 at 15:18

Rotate the labels

test = {{0.875,
0.000361069, -0.137}, {0.9, -0.000429778, -0.1096}, {0.925,
-0.000102596, -0.0822}, {0.95, -0.000234415, -0.0548}, {0.975,
-0.00066855, -0.0274}, {1., -0.00114038, 0}, {1.025, 0.00278551,
0.0274}, {1.05, -0.00148313, 0.0548}, {1.075, 0.00132836,
0.0822}, {1.1, -0.000164138, 0.1096}, {1.125, -0.00036032, 0.137}};

top = {#[[1]], Rotate[ToString[
NumberForm[#[[3]], {5, 4}]],
45 Degree]} & /@ test;


Note that you can simplify the extraction of the data list

ListLinePlot[Most /@ test,
Frame -> True,
FrameTicks -> {
{Automatic, Automatic},
{Automatic, top}},
PlotRange -> All]


EDIT: If you have a large number of points then using a labeled tick for each point is impractical, as the labeled ticks will be too dense to be useful. Instead I recommend that you use Tooltip

ListPlot[List /@ Most /@ test,
Frame -> True,
PlotStyle -> Blue,
PlotMarkers ->
(Tooltip[●, #[[3]]] & /@ test),
Epilog -> Line[Most /@ test]]


• Thank you for the Answer. I can rotate the labels only when I have less number of points. For example, if the data points are very large, then it will not be possible to label all the points of a list. Is there any way do it automatically ? like bottom x axis. – RGG Jan 21 '17 at 16:57