5

Question

Is there a way to include mathematical expressions in PGFPlots, for example, [domain=1/3:e^5/3]?

PGFPlots is fairly useful, however the ability to put mathematical expressions directly into Tikz makes life much easier.

The only way around this problem that I know of is to define a bunch of constants above the before entering the axis environment. I find this a little obnoxious.

enter image description here

MWE

\documentclass{memoir}

\usepackage{tikz}
\usepackage{pgfplots}
\usepackage{amsmath}

\usetikzlibrary{calc, positioning}

\begin{document}

\begin{tikzpicture}[domain=1/3:e^5/3,x=0.1cm, scale=1]

    % Axes
    \draw[help lines]   (-0.2 cm,0) -- (e^5/3+0.2,0) node[right] {$x$};
    \draw[help lines]   (0,-0.2) -- (0,6) node[above] {$y$};
    \draw[gray, thick]  (e^5/3,5) -- (-0.075/0.1,5) node[left] {$y=5$};
    \draw[gray, thick]  (e^5/3,4) -- (-0.075/0.1,4) node[left] {$y=4$};

    % Curves
    \draw[blue, thick] plot[id=lnx] (\x,{ln(3*\x)}) node[right] {$\ln 3x$};
\end{tikzpicture}

\end{document}
9
  • 2
    you can directly write \addplot[domain=1/3:e^5/3] {ln(3*x)} in pgfplots: it applies the math parser. That said, there are still lots of places where the math parser should be invoked... a relic of times when the floating point unit was unavailable. Commented Jul 5, 2013 at 16:18
  • @ChristianFeuersänger: It seems like this doesn't work when the axis is logarithmic. xmode=log,domain=1/3:e^5/3 leads to Could not parse input '1/3' as a floating point number. Is there a way around that?
    – Jake
    Commented Jul 5, 2013 at 16:22
  • @ChristianFeuersänger Yes, that works for the domain. However, try to write \begin{semilogyaxis}[xmin=-1, xmax=e^5/3+5,] ... and you'll run into issues! This is likely one of those places where the math parser could stretch its legs a little.
    – JDG
    Commented Jul 5, 2013 at 16:29
  • @ChristianFeuersänger Anyhow, pgfplots is so useful that I am using it, albeit with tons and tons of \pgfmathsetmacro expressions. Hehehe
    – JDG
    Commented Jul 5, 2013 at 16:31
  • 1
    @Jake and JDG: the next stable version will come with support for the math parser in axis limits and log domains (already committed to git repo). Commented Jul 6, 2013 at 18:58

2 Answers 2

6

You can define a slightly modified version of the domain key to save yourself the trouble of manually parsing the expressions first. If you include the following snippet in your document, you'll be able to type domain*=1/3:e^5/3 even when you're using logarithmic axes (and similarly for xmin, ymax, etc.):

\makeatletter
\pgfplotsset{
    domain*/.code args={#1:#2}{
        \pgfmathsetmacro\pgfplots@lower{#1}
        \pgfmathsetmacro\pgfplots@upper{#2}
        \pgfplotsset{domain=\pgfplots@lower:\pgfplots@upper}
    },
    xmin*/.code={
        \pgfmathparse{#1}
        \pgfplotsset{xmin=\pgfmathresult}
    },
    xmax*/.code={
        \pgfmathparse{#1}
        \pgfplotsset{xmax=\pgfmathresult}
    },  
    ymin*/.code={
        \pgfmathparse{#1}
        \pgfplotsset{ymin=\pgfmathresult}
    },
    ymax*/.code={
        \pgfmathparse{#1}
        \pgfplotsset{ymax=\pgfmathresult}
    }
}
\makeatother

Your plot could be implemented in PGFPlots using something like this:

\documentclass{memoir}

\usepackage{tikz}
\usepackage{pgfplots}
\usepackage{amsmath}

\usetikzlibrary{calc, positioning}

\begin{document}

\makeatletter
\pgfplotsset{
    domain*/.code args={#1:#2}{
        \pgfmathsetmacro\pgfplots@lower{#1}
        \pgfmathsetmacro\pgfplots@upper{#2}
        \pgfplotsset{domain=\pgfplots@lower:\pgfplots@upper}
    }
}
\makeatother

\begin{tikzpicture}
\begin{axis}[
    xmode=log,
    log ticks with fixed point,
    axis lines*=left,
    xlabel=$x$,
    every axis x label/.style={
        at={(rel axis cs:1,0)},
        anchor=west
    },
    ylabel=$y$,
    every axis y label/.style={
        at={(rel axis cs:0,1)},
        anchor=south
    },
    ymin=0,
    xmin=0.1,
    enlarge x limits=false,
    domain*=1/3:e^5/3,
    ytick={0,4,5},
    ymajorgrids,
    yticklabel={$y = \pgfmathprintnumber{\tick}$},
    clip=false
]
\addplot [thick, red] {ln(3*x)} node [anchor=west] {$\ln 3x$};
\end{axis}
\end{tikzpicture}

\end{document}
3
  • This is a great piece of code. However, I tried out the solution and it works in some cases, but does not work in others. For example, I received an error when typing xmin=1/3. In that case, one would still need to make use of commands like \pgfmathsetmacro.
    – JDG
    Commented Jul 5, 2013 at 18:41
  • 1
    @JDG: Well, it only works as a replacement for the domain key, of course. It doesn't do anything to xmin, or ymax, etc. You can define similar code snippets for those: \pgfplotsset{xmin*/.code={\pgfmathparse{#1}\pgfplotsset{xmin=\pgfmathresult}} and then use xmin*=1/3 instead of xmin=1/3. I've edited my answer.
    – Jake
    Commented Jul 5, 2013 at 18:44
  • @Jake has something changed since then? I'm trying \pgfplotsset{xmax=3} before axis and it doesn't change anything despite axis doesn't set xmax.
    – antshar
    Commented May 30 at 12:46
1

Pgfplot Workaround

As an answer, here's the Pgfplot workaround I mentioned, which defines variables using \pgfmathsetmacro before the axis environment. The advantage of this workaround is that it is extremely easy to understand and can be reused easily for similar graphs, which is useful for Calculus 1–3-level homework problems.

enter image description here

MWE

\documentclass{memoir}

\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.8}
\usepackage{amsmath}

\usetikzlibrary{calc, positioning}

\begin{document}

\begin{tikzpicture}[scale=1.5]

\pgfmathsetmacro\xDomainMin{0}
\pgfmathsetmacro\xDomainMax{e^5/3*3}
\pgfmathsetmacro\xMin{-10}
\pgfmathsetmacro\xMax{\xDomainMax+\xDomainMax/50}
\pgfmathsetmacro\yMin{-1}
\pgfmathsetmacro\yMax{6}
\pgfmathsetmacro\xRotation{(e^5/3+5)/2}
\pgfmathsetmacro\yRotation{0}

\begin{semilogyaxis}[    
    axis x line=center,
    axis y line=center,
    axis z line=center,
    xlabel={$x$},
    ylabel={$y$},
    zlabel={$z$},
    axis line style=help lines,
    gray,
    every axis/.append style={font=\tiny},
    width=10cm,
    height=8cm,
    domain=\xDomainMin:\xDomainMax,
    xmin=\xMin, xmax=\xMax,
    ymin=\yMin, ymax=\yMax,
    xtick=\empty,
    ytick={4,5},
    yticklabels={$y=4$,$y=5$},
    area style,
]
    \addplot[id=five, gray, very thin, fill=blue, opacity=0.1] {5} \closedcycle;
    \addplot[id=lnx, white, very thin, mark=none, samples=200, fill=white,]
        {ln(3*x)}\closedcycle;
    \addplot[id=four, gray, very thin, fill=white] {4} \closedcycle;
    \addplot[id=five, gray, very thin,] {5};
    \addplot[id=five, white, very thin, fill=white,
            domain=\xDomainMax-0.1:\xDomainMax+1] {5} \closedcycle;
\addplot[id=lnx, blue, very thin, mark=none, samples=200,]
        {ln(3*x)} node [right]{\color{blue}$\ln x$};

\draw[->,gray, thick]
    (axis cs:6,4.5) arc (-30:-150:8 pt);


\end{semilogyaxis}

\end{tikzpicture}

\end{document}

This site is temporarily in read-only mode and not accepting new answers.

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