2

I have a simple .txt file with 2 columns (x and y coordinates). With pgfplots, it's easy to plot x against y (i.e., all the elements of the 1st column against all the elements of the 2nd column), but how to plot a subset of x against a subset of y using indexing?

This is an example of what I would like to do, written in Matlab code:

x=(1:1:10).';
y=x.^2;

T=table(x,y);
writetable(T,'data.txt');

figure
hold on;
plot(x,y,'k');                       % <-- easy
plot(x(1:3:10),y(1:3:10),'r');       % <-- how to do this?
plot([x(1) x(10)],[y(1) y(10)],'b'); % <-- how to do this?
xlabel('x');
ylabel('y');

The figure generated by the above Matlab code is the following:

enter image description here

The data.txt file generated by the above Matlab code contains the following:

x,y
1,1
2,4
3,9
4,16
5,25
6,36
7,49
8,64
9,81
10,100

Minimum working example with pgfplots:

\begin{tikzpicture}

\begin{axis}[
    width=5cm,
    height=5cm,
    xlabel={$x$},
    ylabel={$y$},
    grid=both,
]

\addplot[line width=1pt, black]
table [x=x, y=y, col sep=comma] 
{data.txt};
    
\end{axis}

\end{tikzpicture}
2
  • Could you show what the Matlab code would output? I am not familiar with this software. Also, does the output txt file contain these backslashes at the end of each line? You may want to look up "filters" in the PGFplots manual. Apr 5, 2023 at 9:38
  • 1
    I updated the question by fixing the output txt file and including the Matlab figure.
    – TheDon
    Apr 5, 2023 at 10:25

1 Answer 1

1

You could use filters:

\documentclass[border=10pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\begin{filecontents}{data.txt}
x,y 
1,1 
2,4 
3,9 
4,16
5,25 
6,36 
7,49 
8,64 
9,81 
10,100
\end{filecontents}

\begin{document}
\begin{tikzpicture}

\begin{axis}[
    %width=5cm,
    %height=5cm,
    xlabel={$x$},
    ylabel={$y$},
    grid=both,
]

\addplot[line width=1pt, black] table [x=x, y=y, col sep=comma] {data.txt};

\addplot[line width=1pt, red, 
    x filter/.expression={(mod(x - 1, 3) == 0 ? \pgfmathresult : NaN)}
] table [x=x, y=y, col sep=comma] {data.txt};

\addplot[line width=1pt, blue, 
    x filter/.expression={(x == 1 || x == 10 ? \pgfmathresult : NaN)}
] table [x=x, y=y, col sep=comma] {data.txt};

\end{axis}

\end{tikzpicture}
\end{document}

enter image description here

If you like to keep the colon notation from Matlab, you could create your custom style:

\documentclass[border=10pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\begin{filecontents}{data.txt}
x,y 
1,1 
2,4 
3,9 
4,16
5,25 
6,36 
7,49 
8,64 
9,81 
10,100
\end{filecontents}

\begin{document}
\begin{tikzpicture}

\tikzset{
    colon notation/.style args={#1(#2:#3:#4)}{
        /pgfplots/#1 filter/.expression={(mod(#1 - #2, #3) == 0 && #1 <= #4 ? \pgfmathresult : NaN)}
    }
}

\begin{axis}[
    %width=5cm,
    %height=5cm,
    xlabel={$x$},
    ylabel={$y$},
    grid=both,
]

\addplot[line width=1pt, black] table [x=x, y=y, col sep=comma] {data.txt};

\addplot[line width=1pt, red, colon notation={x(1:3:10)}] table [x=x, y=y, col sep=comma] {data.txt};

\end{axis}

\end{tikzpicture}
\end{document}

enter image description here


If you need to filter elements depending on their index rather than on their value, you can use \coordindex which start with 0:

\documentclass[border=10pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\begin{filecontents}{data.txt}
x,y 
1,1 
2,4 
3,9 
4,16
5,25 
6,36 
7,49 
8,64 
9,81 
10,100
\end{filecontents}

\begin{document}
\begin{tikzpicture}

\begin{axis}[
    %width=5cm,
    %height=5cm,
    xlabel={$x$},
    ylabel={$y$},
    grid=both,
]

\addplot[line width=1pt, black] table [x=x, y=y, col sep=comma] {data.txt};

\addplot[line width=1pt, red, 
    x filter/.expression={(mod(\coordindex, 3) == 0 ? \pgfmathresult : NaN)}
] table [x=x, y=y, col sep=comma] {data.txt};

\addplot[line width=1pt, blue, 
    x filter/.expression={(\coordindex == 0 || \coordindex == 9 ? \pgfmathresult : NaN)}
] table [x=x, y=y, col sep=comma] {data.txt};

\end{axis}

\end{tikzpicture}
\end{document}
10
  • Thanks for your answer. Just to clarify, the Matlab notation "x(start:step:end)" means "all the elements of the array x from x(start) to x(end) equispaced by step. Is that what your "colon notation" does here? I'm trying to learn to handle elements of an array (i.e., column of a table) by specifying the index and not the value.
    – TheDon
    Apr 5, 2023 at 13:10
  • 1
    Here, it's just a coincidence that each element of x is equal to the corresponding index. If it's confusing, I'll change that in the example.
    – TheDon
    Apr 5, 2023 at 13:11
  • @TheDon Well, colon notation does x(start:step:end), but on the value of x, not on it's index. It might be not quite the same then ... Maybe not even the right thing to use. But the filters should work anyways. Apr 5, 2023 at 15:19
  • I seems to me that also the filter is picking the elements based on the value of x (e.g., "x == 1 || x == 10"), or am I missing something?
    – TheDon
    Apr 5, 2023 at 15:25
  • Perhaps a simpler question would be: how do you select an element of an array (i.e., an element of a column in a table) in pgfplots? In Matlab, this would be simply x(i) to pick the i-th element.
    – TheDon
    Apr 5, 2023 at 15:27

You must log in to answer this question.

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