0

I am trying to adapt the solution here to be inside a pgf axis and use axis coordinates. The solution is based on a draw command like the following

\draw (0,0) \foreach \x in {1,...,5} { -- ++ (1,0.1*\x)};

where the increments are specified instead of points.

I tried using the addplot command instead of draw (So I can specify axis coordinates). However I am running into problems. First the following simple example

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\begin{document}
\begin{tikzpicture}
  \begin{axis}
    \addplot [mark=*] (0,0) -- ++(0.1,0.1) -- ++(0.3, -0.4);
  \end{axis}
\end{tikzpicture}
\end{document}

compiles but the plot is not correct and I get the warning

Package pgfplots Warning: Axis range for axis x is approximately empty; enlarging it (it is [0.0:0.0]) on input line 40.

Specifying the axis limits removes the warning. Additionally, the example

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\begin{document}
\begin{tikzpicture}
  \begin{axis}
    \addplot [mark=*] (0,0) 
     \foreach \x in {1,...,5}
      {  -- ++(1,0.1*\x) };
  \end{axis}
\end{tikzpicture}
\end{document}

does not compile at all. Replacing \foreach by \pgfplotsforeachungrouped does not help.

Is there away to specify the increments in \addplot?

2
  • -- is \draw syntax -not \addplot syntax. You can not use \foreach inside axis. -search for "foreach pgfplots" e.g. : tex.stackexchange.com/questions/170664/… Jul 30 at 13:18
  • Yes, I was surprised that -- actually compiles here. In any case, how would I go about drawing a line based on increments rather than points in pgfplot?
    – Tohiko
    Jul 30 at 13:27
3

There are several things at play here.

  1. You need at least an \addplot command if you want automatic scaling in an axis environment --- otherwise, you need to scale it manually;
  2. As said by @hpekristiansen, foreach does not work as expected in an axis environment, and you have to resort to \pgfplotsinvokeforeach;
  3. In an axis environment, the (default since 1.11) axis cs: coordinate system accepts only absolute coordinates; you need to use the axis direction cs: coordinate system to do incremental moves;
  4. And finally, it seems that using the correct coordinates the \foreach does work, as notice by @hpekristiansen.

Example:

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\begin{document}
\begin{tikzpicture}
    % you need to manually scale the axis if you do not use "addplot"
    \begin{axis}[xmin=-5,xmax=5,ymin=-5,ymax=5]
      % let's unfold the "foerach" manually to see how it works
      % with the correct coordinate system
      \draw[red] (0,0) -- ++ (axis direction cs:1,0.1) 
          -- ++(axis direction cs:1,0.2)
          -- ++(axis direction cs:1,0.3)
          -- ++(axis direction cs:1,0.4)
          -- ++(axis direction cs:1,0.5);
      % to have the "foreach" function, we must use "pgfplotsinvokeforeach",
      % which accepts only full statement. Let's use a 
      % temporary coordinate to simulate the "last point"
      \coordinate (last) at (0,-0.5);
      \pgfplotsinvokeforeach{1,...,5}{%
        \draw[blue] (last) -- ++ (axis direction cs:1,0.1*#1) coordinate(last);}
       % in this case the plain foreach seems also to work
       % I do not know why...
       \draw[green] (0,-1) \foreach \x in {1,...,5} 
            { -- ++ (axis direction cs: 1,0.1*\x)};
  \end{axis}
\end{tikzpicture}
\end{document}

enter image description here

4
  • This is exactly what I was looking for. Thanks. Just to check, is there no way to have a single draw command like before? I mean of course the draw command being outside the loop and having the for loop construct the path.
    – Tohiko
    Jul 30 at 14:35
  • 1
    @Tohiko I think it's impossible --- I tried a bit of expansion tricks to no avail. I will be happy to be wrong! ;-)
    – Rmano
    Jul 30 at 14:38
  • I think that @hpkristiansen found the solution (added, thanks!)
    – Rmano
    Jul 30 at 14:46
  • +1. I need to look into axis direction cs:. This could also be made with marks! Jul 30 at 22:15
2

One option is to use the command \pgfplotsinvokeforeach (taken from this answer).

Here is the code. (I've also changed the -- from your addplot to coordinates. This was taken from the PGFPlots Gallery.)

\documentclass{article}

\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\begin{document}
    \begin{tikzpicture}
        \begin{axis}
            \pgfplotsinvokeforeach{1, ..., 5} {
                \addplot coordinates {
                    (0, 0)
                    (1, 0.1*#1)
                };
            }
        \end{axis}
    \end{tikzpicture}
\end{document}

and generates this image:

multiple addplot


Edit

I misunderstood the question before. The following should work, although it might not be the "best" solution. I define a coordinate (current) from which I draw the next segment. Then I define a coordinate (tmp) (using \path) where the next position is and then I redefine (current) to be (tmp).

\begin{tikzpicture}
    \begin{axis}[
        xmin=0,
        xmax=5,
        ymin=0,
        ymax=2,
        ]
    
    \coordinate (current) at (axis cs: 0, 0);
    
    \pgfplotsinvokeforeach{1, ..., 5} {
        \draw[mark=*] (current) -- ++(axis cs: 1, 0.1*#1);
        \path (current) ++(axis cs: 1, 0.1*#1) coordinate (tmp);
        \coordinate (current) at (tmp);
    }
    \end{axis}
\end{tikzpicture}

Alternatively you could use \coordinate (tmp) at ($(current)+(axis cs: 1, 0.1*#1)$); to define (tmp), though this requires \usetikzlibrary{calc} in the preamble. Sadly, apparently one needs to pass in xmin, ..., ymax manually, if addplot is never used (at least nothing is drawn for me, if I don't pass them in manually). This is the generated picture:

continuous plot

2
  • This creates five different plots. -I do not believe that is what OP is after. Jul 30 at 13:49
  • Notice that mark=* does not work as an argument of \draw...
    – Rmano
    Jul 30 at 14:41
2

samples at already has a \foreach syntax, so there is no need to use \foreach.

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\begin{document}
\begin{tikzpicture}
  \begin{axis}
    \addplot[mark=*, samples at={0,...,5}] (\x, 0.1*\x);
  \end{axis}
\end{tikzpicture}
\end{document}

Linear graph

Edit:

Here is a solution, that does not use \addplot but \draw - also a solution that adds marks:

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\begin{document}
\begin{tikzpicture}
  \begin{axis}[xmin=-1, xmax=12, ymin=-1, ymax=10]
    \draw[thick] (0,0) \foreach \x in {1,...,5} { -- ++ (1,0.1*\x)};
    \draw[red] (0,0) \foreach \x in {1,...,5} { -- plot[mark=*] coordinates { ++(1,0.1*\x)}};
  \end{axis}
\end{tikzpicture}
\end{document}

Graph

This does not work right now because I used \foreach inside axis - it need to be rewritten with PGFPlots variants of \foreach.

Edit:

I found that it is not possible to do it like that with PGFPlots variants of \foreach. An alternative is to use a named coordinate as in the answer by @Simon, so that it can be drawn piecewise. -but with plot, so that marks can be made:

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.17}
\begin{document}
\begin{tikzpicture}
\begin{axis}[xmin=0, xmax=5, ymin=0, ymax=2]
\coordinate (current) at (0, 0);  
\pgfplotsinvokeforeach{1, ..., 5} {
  \draw (current) -- plot[mark=*] coordinates {++(1, 0.1*#1)} coordinate (current);
}
\end{axis}
\end{tikzpicture}
\end{document}

Graph with marks

For some reason, the entire plot changes when xmin is changed to e.g. -1. I can not explain this strange behaviour.

5
  • This does not plot increments but the actual points. If the increment are (1,1) (2,2) and (3,3), the points should be at (1,1), (3,3) and (6,6). This is what \draw (1,1) -- ++(2,2) -- ++(3,3); would do.
    – Tohiko
    Jul 30 at 13:54
  • \addplot[mark=*, samples at={0,...,5}] (\x, 0.5*0.1*\x*\x+0.5*0.1*\x); follows same line as \draw (0,0) \foreach \x in {1,...,5} { -- ++ (1,0.1*\x)}; Jul 30 at 13:57
  • Thanks. As I said in my original post. I simplified the example. The real case (or a Brownian motion) has to be described with increments.
    – Tohiko
    Jul 30 at 13:59
  • @Tohiko: I do not know how to do that. Why not just use \draw inside axis? Jul 30 at 14:01
  • Hmmm... the last point y should be at 0.1+0.2+0.3+0.4+0.5 = 1.5, no? It works if you use \draw[green] (0,-1) \foreach \x in {1,...,5} { -- ++ (axis direction cs: 1,0.1*\x)};
    – Rmano
    Jul 30 at 14:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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