24

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....

Joseph Wright
  • 259,911
  • 34
  • 706
  • 1,036

3 Answers3

31

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

mkrnr
  • 113
Jake
  • 232,450
  • @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 09:55
  • Comma separation solved here: https://tex.stackexchange.com/a/448517/95657 – Spenhouet 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}
Werner
  • 603,163
Ditma1
  • 1