4

In the following MWE and graph,

Currently, the following graph consists of logarithmically scaled X and Y axis, with units of:

  • log(years) on the abscissa (X) axis, and
  • log($) on the (traditional) ordinate (Y) axis, respectively.

However, while the:

  • LEFT (Y) (traditional) ordinate axis is base-10 logarithmic, the

  • RIGHT (X) (new, unique) ordinate axis is meant to be linear, e.g. non-logarithmic.

Both the LEFT and RIGHT ordinate axis are meant to be synchronized, e.g. what logarithmic values are displayed on the LEFT ordinate axis need to be equivalent in non-logarithmic terms to the values that are displayed on the RIGHT ordinate axis.

On the current graph below, the LEFT ordinate axis is exactly as I would like it to appear, but the RIGHT ordinate axis is NOT. The abscissa axis is exactly as it needs to be.

The challenge is that the LEFT ordinate axis IS logarithmic, but the RIGHT ordinate axis is NOT.

So I'd like for the RIGHT ordinate axis to appropriately show 'tick' marks at 1,050($), 1,100($) and 1,150($) that roughly correspond to the values on the LEFT ordinate axis of 10^3.02, 10^3.04 and 10^3.06.

On the graph below, at the level indicated on the LEFT ordinate axis by the label at 10^3.02 log($), on the RIGHT ordinate axis I would like to see (approximately, not exactly) the non-logarithmic 'tick' mark and label of 1,050($).

Similarly, at the level indicated on the LEFT ordinate axis by the label at 10^3.06 log($), on the RIGHT ordinate axis I would like to see (approximately, not exactly) the non-logarithmic 'tick' mark and label of 1,150($).

Here is the current MWE:

\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\usepackage{amsmath}

\begin{document}
\begin{tikzpicture}
\begin{axis}[
  name=left axis,
  xmode=log,
  xlabel={Year (log scale)},
  ylabel={Cumulative Future Asset Value (log \$ scale)},
  ylabel near ticks,
  ylabel shift = -0.35em,
  legend pos=north west,
  ymajorgrids=true,
  grid style=dashed,
  xtick={1,10,100},
  xticklabels={1,10,100},
  ytick={3.00, 3.02, 3.04, 3.06},
  yticklabels={$10^{3.00}$, $10^{3.02}$, $10^{3.04}$, $10^{3.06}$},
  y tick label style={font=\large},
]

% For r=5%
\addplot[color=blue,domain=1:100,samples=100]
  {log10(1000 * (1 + 0.05)^(log10(\x+1)))};
\addlegendentry{$r=5\%$}

% For r=7%
\addplot[color=red,domain=1:100,samples=100]
  {log10(1000 * (1 + 0.07)^(log10(\x+1)))};
\addlegendentry{$r=7\%$}

\end{axis}

\begin{axis}[
  at={(left axis.outer north east)},anchor=outer north west,
  yshift=-0.2cm,
  xshift=-0.161cm,
  yticklabel style={font=\large},
  ytick={2000, 3000, 4000, 5000, 6000, 7000, 8000},
  yticklabels={2000, 3000, 4000, 5000, 6000, 7000, 8000},
  ylabel near ticks,
  ylabel={Absolute Future Asset Value (\$)},
  xtick=\empty,
  axis y line*=right,
  axis x line=none,
  scale only axis,
  ymode=log,
  yticklabel={\pgfmathprintnumber[fixed, precision=0, use comma]{\tick}},
]
\end{axis}

\end{tikzpicture}
\end{document}

The graph as it stands now:

Pgfplot with two separate, but synchronized, axis on left and right of graph.

Currently, the graph consists of logarithmically scaled X and Y axis, with units of log(years) on the abscissa (X) axis, and log($) on the (traditional) LEFT ordinate (Y) axis, respectively.

The unique, non-traditional, non-logarithmic RIGHT linear $ ordinate axis is meant to assist the reader who may not understand how to interpret the logarithmic values on the LEFT log($) ordinate axis.

I've scanned through Dr. Christian Feuersänger's vast pgfplots package documentation, but did not see any specific examples of any such dual-ordinate graphics.

FWIIW, I spent of the order of 15+ hours online working with AI in an attempt to get what I was looking for. The biggest hurdle I (and the AI) were working around was the fact that this particular AI could not plot the graphics from LaTeX code, and therefor could not envision or 'see' the output of the code it was suggesting. A major drawback.

To date, and this is where it got tricky working with AI, I (or should I say we?) was (were) able to construct the graph as it now stands. Unfortunately, adjusting the label and 'tick' marks on the RIGHT ordinate axis proved elusive.

This might all just amount to an empty exercise that the pgfplots package cannot handle, confirming the difficulty the AI had to deal with.

Please feel free to pepper me with whatever questions you might have. The is NOT a traditional concept that I am attempting to present, particularly for (economist-type) readers who may have never seen such a graph.

Many thanks.

UPDATE: Using Rmano's code (See below), and a few tweaks, the final code for the dual axis graphical plot is:

\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\usepackage{amsmath}

\begin{document}
\begin{tikzpicture}
    \pgfplotsset{range/.style={%
        xmin = 0.9,
        xmax = 200,
        ymin = 3.0,
        ymax= 3.07,
    }}
    \begin{axis}[
        range,
        name=left axis,
        xmode=log,
        xlabel={Year (log scale)},
        ylabel={Cumulative Future Asset Value (log \textdollar{} scale)},
        legend pos=north west,
        ymajorgrids=true,
        grid style=dashed,
        xtick={1,10,100},
        xticklabels={1,10,100},
        ytick={3.00, 3.02, 3.04, 3.06},
        yticklabels={$10^{3.00}$, $10^{3.02}$, $10^{3.04}$, $10^{3.06}$},
        ylabel near ticks,
        y tick label style={font=\large},
        axis y line* = left,
              ]
        % For r=5%
        \addplot[color=blue,domain=1:100,samples=100]
            {log10(1000 * (1 + 0.05)^(log10(\x+1)))};
        \addlegendentry{$r=5\%$}
        % For r=7%
        \addplot[color=red,domain=1:100,samples=100]
            {log10(1000 * (1 + 0.07)^(log10(\x+1)))};
        \addlegendentry{$r=7\%$}
    \end{axis}
    \begin{axis}[
        range,
        xmode=log,
        yticklabel style={font=\large},
        ylabel near ticks,
        % this is the same value as the other vertical axis, no sense
        % to have a different label...
        ylabel={Absolute Future Asset Value (\textdollar)},
        % we need ticks at the correct position. fpeval have no log10
        % surely can be automated
        ytick={\fpeval{ln(1000)/ln(10)},
            \fpeval{ln(1050)/ln(10)},
            \fpeval{ln(1100)/ln(10)},
            \fpeval{ln(1150)/ln(10)}},
        yticklabels={{1,000},{1,050},{1,100},{1,150}},
        axis y line*=right,
        axis x line=none,
        ]
    \end{axis}
\end{tikzpicture}
\end{document}

and the final graph is:

Dual Ordinate axis graph of logarithmic Asset Values plotted against logarithmic years.

7
  • I am not sure I understand. The data can be plotted with a logarithmic ordinate axis, or not; linear and logarithmic axis are not proportional. But maybe you just want a secondary vertical axis that, although is logarithmic, show the natural values as ticks?
    – Rmano
    Jul 19, 2023 at 20:49
  • @Rmano - Yes...Good catch! Notwithstanding my text that states that the RIGHT ordinate axis is non-logarithmic, TO BE EXACT, it is the LABELS on the RIGHT axis that need to express the non-logarithmic values corresponding to the 'tick' marks at 10^3.02, 10^3.04 and 10^3.06. Hiding behind my labeling of the RIGHT ordinate axis as non-logarithmic is the fact that you CANNOT have the scale on one side of the graph be logarithmic and the other side non-logarithmic. Each graph can have only ONE Y scale, either non-logarithmic OR non-logarithmic, but NOT both. The LABELS however, can be interchanged Jul 19, 2023 at 21:05
  • Too late now. I'll try a shot at it tomorrow if nobody answer it. 😉
    – Rmano
    Jul 19, 2023 at 21:09
  • One \addplot cannot match both a logrithmic and cartesian grid at the same time. Now you can create non-regular tick marks which show the log values (at least over one decade or so). Jul 19, 2023 at 23:19
  • @John Kormylo - I think that may have been the challenge with the strategy that we were using. Perhaps the best way to go would be to NOT use pgfplots for the second RIGHT ordinate axis, but construct a tikz overlay to accomplish what I'd like to see. Are there any examples of, or online links to, code that demonstrate how LateX can implement your suggestion? Jul 19, 2023 at 23:31

2 Answers 2

5

This is my other interpretation of the problem. Notice that for pgfplots, the vertical axis on the left is linear, no logarithmic. The "logarithmic" is created manually with the log10 in the plot function. The function is plotted against a linear axis that ranges from more or less 3.0 to 3.065.

Once the function is plotted, you can't have a linear axis matching the logarithmic one (or the other way around). I suppose you want an auxiliary axis with the explicit value of $10^{3.02}$ etc...

In this case, when using multiple axes, the best thing, in my opinion, is to fix the x and y ranges (you could use a common style for this). Then I manually calculated the ytick positions on the right vertical axis, which is the same as the left one.

\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\usepackage{amsmath}

\begin{document}
\begin{tikzpicture}
    \pgfplotsset{range/.style={%
        xmin = 0.9,
        xmax = 200,
        ymin = 3.0,
        ymax= 3.07,
    }}
    \begin{axis}[
        range,
        name=left axis,
        xmode=log,
        xlabel={Year (log scale)},
        ylabel={Cumulative Future Asset Value (log \textdollar{} scale)},
        legend pos=north west,
        ymajorgrids=true,
        grid style=dashed,
        xtick={1,10,100},
        xticklabels={1,10,100},
        ytick={3.00, 3.02, 3.04, 3.06},
        yticklabels={$10^{3.00}$, $10^{3.02}$, $10^{3.04}$, $10^{3.06}$},
        ylabel near ticks,
        y tick label style={font=\large},
        axis y line* = left,
              ]
        % For r=5%
        \addplot[color=blue,domain=1:100,samples=100]
            {log10(1000 * (1 + 0.05)^(log10(\x+1)))};
        \addlegendentry{$r=5\%$}
        % For r=7%
        \addplot[color=red,domain=1:100,samples=100]
            {log10(1000 * (1 + 0.07)^(log10(\x+1)))};
        \addlegendentry{$r=7\%$}
    \end{axis}
    \begin{axis}[
        range,
        xmode=log,
        yticklabel style={font=\large},
        ylabel near ticks,
        % this is the same value as the other vertical axis, no sense
        % to have a different label...
        %%% ylabel={Absolute Future Asset Value (\textdollar)},
        % we need ticks at the correct position. fpeval have no log10
        % surely can be automated
        ytick={\fpeval{ln(1000)/ln(10)},
            \fpeval{ln(1050)/ln(10)},
            \fpeval{ln(1100)/ln(10)},
            \fpeval{ln(1150)/ln(10)}},
        yticklabels={1000,1050,1100,1150},
        axis y line*=right,
        axis x line=none,
        ]
    \end{axis}
\end{tikzpicture}
\end{document}

enter image description here

7
  • @ Rmano - Your answer is PRECISELY the image I had imagined from the beginning. As I outlined in my comment to Jasper Habicht below, your answer (I believe) correctly plots the 'tick' marks for the 1,050, 1,100, and 1,150 labels corresponding to the flowing logarithmic values: corresponding logarithmic values: [log(1,050)=]3.021189, [log(1,100)=]3.041393, and [log(1,150)=]3.060698. If I may make one request before I accept your answer, can you confirm that what I am seeing is what you have coded? Thank you. (For the curious, 10^3.00 = 1,000 EXACTLY, so no extra tick mark is required @ 1000). Jul 23, 2023 at 3:38
  • @ Rmano - As an aside, would it be possible to add the following title to the RIGHT ordinate axis: "Absolute Future Asset Value ($)". Thanks again for your superb answer!! Jul 23, 2023 at 3:42
  • How do I add commas to the labels on the RIGHT ordinate axis to become, 1,000, 1,050, 1,100, and 1,150 without the code becoming confused as to which commas separate each of the four labels, and which commas are endemic to the labels themselves? This is just so excellent! Jul 23, 2023 at 3:50
  • Look at the comment in the code... Ticks position is calculated with the log operation, so they are exact. The shown label are in ytickslabel, so just add the commas (or whatever) there. Finally, the axis label you want is in the code, just commented out, because I do not understand why you want different labels for the same number... But just uncomment that ylabel.
    – Rmano
    Jul 23, 2023 at 6:55
  • 1
    Note that ytick={log10(1000), log10(1050), log10(1100), log10(1150)}, also works, i.e., no need for fpeval.
    – Marijn
    Jul 24, 2023 at 19:05
2

Not fully sure whether this is what you're after, but if you want to draw two ordinates, you need to set the option scale only axis to both axes in order to match the scaling of both axes (how to use two ordinates is actually described in section 4.9.11 of the current PGFPlots manual, but maybe the AI you used hasn't read this part in detail yet ... 😉):

\documentclass[border=10pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
%\usepackage{amsmath}

\begin{document}
\begin{tikzpicture}
\begin{axis}[
  name=left axis,
  scale only axis,
  xmode=log,
  xlabel={Year (log scale)},
  ylabel={Cumulative Future Asset Value (log \$ scale)},
  ylabel near ticks,
  ylabel shift = -0.35em,
  legend pos=north west,
  ymajorgrids=true,
  grid style=dashed,
  xtick={1,10,100},
  xticklabels={1,10,100},
  ytick={3.00, 3.02, 3.04, 3.06},
  yticklabels={$10^{3.00}$, $10^{3.02}$, $10^{3.04}$, $10^{3.06}$},
  y tick label style={font=\large},
  ytick pos=left,
]

% For r=5%
\addplot[color=blue,domain=1:100,samples=100]
  {log10(1000 * (1 + 0.05)^(log10(\x+1)))};
\addlegendentry{$r=5\%$}

% For r=7%
\addplot[color=red,domain=1:100,samples=100]
  {log10(1000 * (1 + 0.07)^(log10(\x+1)))};
\addlegendentry{$r=7\%$}

\end{axis}

\begin{axis}[
  yticklabel style={font=\large},
  ytick distance={1/6},
  yticklabels={0, 2000, 3000, 4000, 5000, 6000, 7000, 8000},
  ylabel near ticks,
  ylabel={Absolute Future Asset Value (\$)},
  xtick=\empty,
  axis y line*=right,
  axis x line=none,
  scale only axis,
  ymin=0,
  ymax=1,
]
\end{axis}

\end{tikzpicture}
\end{document}

enter image description here

Using this approach, you will get a warning that one of the plots is empty (which is obvious since the second axis environment does not contain any plot at all). You can place an invisible plot (such as \addplot[draw=none] coordinates {(0,0) (1,1)};) to get rid of the warning or just ignore it.


Alternatively (and as you already pointed to in your comment), you could draw an overlay, that is, the right axis manually, for example like this:

\documentclass[border=10pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
%\usepackage{amsmath}

\begin{document}
\begin{tikzpicture}
\begin{axis}[
  name=left axis,
  xmode=log,
  xlabel={Year (log scale)},
  ylabel={Cumulative Future Asset Value (log \$ scale)},
  ylabel near ticks,
  ylabel shift = -0.35em,
  legend pos=north west,
  ymajorgrids=true,
  grid style=dashed,
  xtick={1,10,100},
  xticklabels={1,10,100},
  ytick={3.00, 3.02, 3.04, 3.06},
  yticklabels={$10^{3.00}$, $10^{3.02}$, $10^{3.04}$, $10^{3.06}$},
  y tick label style={font=\large},
  ytick pos=left,
]

% For r=5%
\addplot[color=blue,domain=1:100,samples=100]
  {log10(1000 * (1 + 0.05)^(log10(\x+1)))};
\addlegendentry{$r=5\%$}

% For r=7%
\addplot[color=red,domain=1:100,samples=100]
  {log10(1000 * (1 + 0.07)^(log10(\x+1)))};
\addlegendentry{$r=7\%$}

\end{axis}

\draw (left axis.north east) -- (left axis.south east)
    node[midway, xshift=30pt, anchor=north, rotate=90] 
        {Absolute Future Asset Value (\$)}
    foreach \y [count=\i] in {2000, 3000, ..., 8000} {
        coordinate[pos={1-1/6*(\i-1)}] (y-\i) 
        (y-\i) node[right, font=\large] {\y} 
    };

\foreach \i in {1, ..., 7} {
    \draw[thin, lightgray] (y-\i) -- ++(-0.15cm,0);
}

\end{tikzpicture}
\end{document}

(Or create the axis inside the axis environment using

\draw (axis description cs:1,0) -- (axis description cs:1,1)
    node[midway, xshift=30pt, anchor=north, rotate=90] 
        {Absolute Future Asset Value (\$)}
    foreach \y [count=\i] in {2000, 3000, ..., 8000} {
        coordinate[pos={1-1/6*(\i-1)}] (y-\i) 
        (y-\i) node[right, font=\large] {\y} 
    };

\draw[thin, lightgray] 
    foreach \i in {1, ..., 7} {
        (y-\i) -- ([xshift=-0.15cm]y-\i)
    };

)

enter image description here

6
  • So probably I did not understand the question... I thought that the right ordinate should have the values of the left one. I mean, at 10^{3.02} level, it should read 1047, at 10^{3.04}, 1096... but really, I am not sure. Clearly, if the value is the same I do not understand while the y legends are different...
    – Rmano
    Jul 20, 2023 at 8:16
  • 1
    @Rmano To be honest, I am not sure either. Maybe the right axis should be logarithmic as well ... I'll just wait for the OP to reply to this. I wanted at least to give some starting points as to how to add another axis to the plot. Jul 20, 2023 at 8:21
  • @Jasper Habicht - Thank you for your answer. I realize my instructions may have been confusing at best. FWIIW, Rmano's answer is closer to what I was looking for, with the Absolute Future value on the RIGHT ordinate axis values representing the mirror of the 10^3.02, 10^3.04, and 10^3.06 values on the LEFT ordinate axis, e.g. 1047.129, 1096.478, and 1148.154 respectively. To complicate matters worse, on the RIGHT ordinate axis, I am looking for the 'tick' marks (and their labels) to appear at the following equivalent locations on the RIGHT ordinate axis: 1,050, 1,100, & 1,150 respectively. Jul 23, 2023 at 2:37
  • @Jasper Habicht - (continued) What I initially had a hard time understanding was that there is only a SINGLE logarithmic axis, but that the 'tick' marks and labels on the RIGHT ordinate axis (1,050, 1,100, and 1,150) were to be placed as a reflection of the following corresponding logarithmic values: [log(1,050)=]3.021189, [log(1,100)=]3.041393, and [log(1,150)=]3.060698. The end result is that the 'tick' marks and labels on the LEFT ordinate axis are APPROXIMATELY but NOT exactly reflected one-for-one at the same elevation with the 'tick' marks and labels on the RIGHT ordinate axis. Jul 23, 2023 at 3:09
  • @Jasper Habicht - (continued) The rounded values of 10^3.02, 10^3.04, and 10^3.06, on the LEFT ordinate axis are an APPROXIMATE reflection of the 1,050, 1,100, and 1,150 values on the RIGHT ordinate axis, but NOT exactly at the same elevations on both the LEFT and RIGHT ordinate axises. Thank you again for you answer. Jul 23, 2023 at 3:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .