10
$\begingroup$

I am trying to plot 2 plots together with a common x-axis and different y-axis.

I have tried implementing the modules shown in 1 Plot, 2 Scale/Axis however I do not see the full range of data in the plot, the y-axis for the second plot is truncated (at y = 400 with a few different sample data sets). The examples given in the above link do not truncate the range plotted. I would also like to modify the modules so that the x-axis commences at 1 rather than 0.

Any suggestions either to modify the module (apologies but I do not understand how the range is set to modify myself), or if there is another simple method (I need to do this many times over).

ETA: Also having difficulty adding FrameLabels to these plots. If these can be added either as an argument to the module, or otherwise that'd be useful.

TwoAxisListLinePlot[{f_, g_}] := 
 Module[{fgraph, ggraph, frange, grange, fticks, 
   gticks}, {fgraph, ggraph} = 
   MapIndexed[
    ListLinePlot[#, Axes -> True, 
      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, Transparent}}, 
   FrameTicks -> {{fticks, gticks}, {Automatic, Automatic}}]]

data1 = {1, 7, 2000, 5, 4, 7, 164};
data2 = {1, 4, 3, 5, 2, 6, 8};
TwoAxisListLinePlot[{data1, data2}]

enter image description here

$\endgroup$

3 Answers 3

5
$\begingroup$

To fix the first issue, you need to set PlotRange->All in the first call to ListLinePlot. Then it's pretty easy to adapt this to take lots of other optional arguments as well,

TwoAxisListLinePlot[{f_, g_}, plotopts : OptionsPattern[]] := 
 Module[{fgraph, ggraph, frange, grange, fticks, 
   gticks}, {fgraph, ggraph} = 
   MapIndexed[
    ListLinePlot[#, 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, Transparent}}, 
   FrameTicks -> {{fticks, gticks}, {Automatic, Automatic}}, 
   Evaluate[FilterRules[{plotopts}, Options[ListLinePlot]]]]]

data1 = {1, 7, 2000, 5, 4, 7, 164};
data2 = {1, 4, 3, 5, 2, 6, 8};
TwoAxisListLinePlot[{data1, data2}]

enter image description here

TwoAxisListLinePlot[{data1, data2}, FrameLabel -> {"X", "Y", , "Z"}, 
 PlotLabel -> "This is my plot", BaseStyle -> 15, ImageSize -> 600]

enter image description here

Keep in mind, this version of TwoAxisPlot will not work if you, like I, have a custom init.m file that sets certain options on all the plotting functions every time the kernel loads. Specifically, I have SetOptions[ListLinePlot, PlotRange -> All, Frame -> True, Axes -> False] load automatically, which breaks the 2 axis plotting function since it extracts the Ticks rather than the FrameTicks. An easy enough thing to fix though.

$\endgroup$
7
$\begingroup$

The solution is in the accepted answer to the question you linked to. Only some minor modifications are required.

C1 = RGBColor[0.368, 0.507, 0.710];
C2 = RGBColor[0.881, 0.611, 0.142];

data1 = {1, 7, 2000, 5, 4, 7, 164};
data2 = {1, 4, 3, 5, 2, 6, 8};

p1 =
 ListLinePlot[
  data1,
  ImagePadding -> 45,
  Frame -> {True, True, True, False},
  FrameLabel -> "Blue Series",
  FrameStyle -> {Automatic, C1, Automatic, Automatic},
  FrameTicks -> {All, All, None, None},
  GridLines -> Automatic,
  ImageSize -> Large,
  PlotRange -> {{1, Automatic}, All},
  PlotStyle -> C1];

p2 =
 ListLinePlot[
  data2,
  Axes -> False,
  ImagePadding -> 45,
  Frame -> {False, False, False, True},
  FrameLabel -> {None, None, None, "Orange Series"},
  FrameStyle -> {Automatic, Automatic, Automatic, C2},
  FrameTicks -> {None, None, None, All},
  ImageSize -> Large,
  PlotRange -> {{1, Automatic}, All},
  PlotStyle -> C2];

Overlay[{p1, p2}]

enter image description here

$\endgroup$
1
  • $\begingroup$ The list of four elements, one for each side, somehow stopped working for FrameLabel and FrameTicks sometime between v9 and v11.1.1. The syntax that works in v11.1.1 is {{Left, Right},{Bottom,Top}}, as is discussed in mathematica.stackexchange.com/a/158126/46335 $\endgroup$ Oct 18, 2017 at 19:07
2
$\begingroup$

Another approach using rescaled data:

 numDivs=5;
 With[{ticks1 = FindDivisions[{Min@data1, Max@data1}, numDivs], 
       ticks2 = FindDivisions[{Min@data2, Max@data2}, numDivs]}, 
 ListLinePlot[{Rescale@data1, Rescale@data2}, Frame -> True, PlotRange -> All, 
  FrameTicks -> {{{Rescale@ticks1, 
       ticks1}\[Transpose], {Rescale@ticks2, 
       ticks2}\[Transpose]}, {Automatic, None}}, 
  FrameTicksStyle -> {{Darker@Blue, Darker@Darker@Red}, {Black, 
     Black}}]]

Mathematica graphics

You can adjust the number of ticks as required, FindDivisions is convenient but sometimes has its own ideas about the number of divisions it actually chooses.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.