21

I'm using pgfplots extensively and I'd like to avoid having to write legends every time, since all the text files I want to plot have explicit headers.

As a comparison, \pgfplotstabletypeset makes a nice table instantly with my data, and I'm looking for a similar way to get graphs in an easier way than having to specify each column, legend, etc....

27

You can access the column names of a PGFplots table through the macro \pgfplotstablegetcolumnnamebyindex{<index>}\of{<table macro>}\to{<macro>}. You can use this while looping through the columns of a table using \pgfplotsinvokeforeach{<list>}{<commands>} to add the column names as legend entries.

I've written a \plotfile macro that takes a filename as argument and then plots all columns starting from the second column against the first column:

\documentclass{article}
\usepackage{pgfplots}
\usepackage{filecontents}

\begin{filecontents}{testdata.dat}
Time Distance Velocity Something
0 0 1 0.2
1 1 1 0.3
1.999 1.999 1 0.4
2 2 0 0.4
3 2 0 0.5
\end{filecontents}


\newcommand{\plotfile}[1]{
    \pgfplotstableread{#1}{\table}
    \pgfplotstablegetcolsof{#1}
    \pgfmathtruncatemacro\numberofcols{\pgfplotsretval-1}
    \pgfplotsinvokeforeach{1,...,\numberofcols}{
        \pgfplotstablegetcolumnnamebyindex{##1}\of{\table}\to{\colname}
        \addplot table [y index=##1] {#1}; 
        \addlegendentryexpanded{\colname}
    }
}

\begin{document}
\begin{tikzpicture}
\begin{axis}[legend pos=north west]
\plotfile{testdata.dat}
\end{axis}
\end{tikzpicture}
\end{document}

plotting columns from a table

  • @Jake, i tried this solution where instead of defining \newcommand{\plotfile}[1], i simply apply it below \begin{axis} and it didn't work. I am interesting to know why... What is the reason? – Eagle Feb 16 '12 at 9:55
  • Comma separation solved here: tex.stackexchange.com/a/448517/95657 – Spen Aug 30 '18 at 15:06
4

I used the following to read a file, plot some columns and add legend entries, this worked fine:

\begin{figure}[!t]%
\centering
\begin{tikzpicture}
\begin{axis}[
width=\columnwidth, height=0.7\columnwidth,
xlabel={Frequency (GHz)}, ylabel={Image rejection (dB)}]
\pgfplotstableread{data/Simulation.txt}\SimIR
\foreach \n in {3,4,...,6} {
  \addplot table[x=IF,y index=\n]{\SimIR};
  \pgfplotstablegetcolumnnamebyindex{\n}\of{\SimIR}\to{\colname}
  \addlegendentryexpanded{\colname}
}%
\end{axis}
\end{tikzpicture}
\caption{Image rejection versus frequency.}%
\label{fig:IR}%
\end{figure}
  • If I understand correctly, the main differences between this and my answer are the use of \foreach instead of \pgfplotsforeachungrouped and the hard-coding of the columns to be plotted? – Jake Jan 25 '14 at 15:49
0

Here is my comment as an answer because I cannot comment and was searching for this solution for hours.

@Eagle asked:

@Jake, I tried this solution where instead of defining \newcommand{\plotfile}[1], I simply apply it below \begin{axis} and it didn't work. I am interesting to know why... What is the reason?

When using the

\pgfplotsinvokeforeach{1,...,\numberofcols}{}

not within a function, a single # needs to be used as index.

\documentclass{article}
\usepackage{pgfplots}
\usepackage{filecontents}

\begin{filecontents}{testdata.dat}
Time Distance Velocity Something
0 0 1 0.2
1 1 1 0.3
1.999 1.999 1 0.4
2 2 0 0.4
3 2 0 0.5
\end{filecontents}


\begin{document}
\begin{tikzpicture}
\begin{axis}[legend pos=north west]
    \pgfplotstableread{testdata.dat}{\table}
    \pgfplotstablegetcolsof{\table}
    \pgfmathtruncatemacro\numberofcols{\pgfplotsretval-1}
    \pgfplotsinvokeforeach{1,...,\numberofcols}{
        \pgfplotstablegetcolumnnamebyindex{#1}\of{\table}\to{\colname}
        \addplot table [y index=#1] {\table}; 
        \addlegendentryexpanded{\colname}
    }
\end{axis}
\end{tikzpicture}
\end{document}

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.