1

I have a csv file index.dat with data

Year,0-19 years,20-39 years,40-59 years,60-79 years,80-99 years,100 years+
2000,100,100,100,100,100,100
2001,101,102,101,102,101,102
...

I am trying to plot this with pgfplots.

I have made this script

\begin{tikzpicture}

\begin{axis}[
    width=\textwidth,
    height=0.5\textwidth,
    grid=both,
    xmin=2000,
    xmax=2010,
    xticklabel style={/pgf/number format/1000 sep=, rotate=45},
    ymin=80,
]

\addplot table [x=Year, y=0-19 years, col sep=comma] {./data/index.dat};
\addlegendentry{0-19 years}

\addplot table [x=Year, y=20-39 years, col sep=comma] {./data/index.dat};
\addlegendentry{20-39 years}

\addplot table [x=Year, y=40-59 years, col sep=comma] {./data/index.dat};
\addlegendentry{40-59 years}

\addplot table [x=Year, y=60-79 years, col sep=comma] {./data/index.dat};
\addlegendentry{60-79 years}

\addplot table [x=Year, y=80-99 years, col sep=comma] {./data/index.dat};
\addlegendentry{80-99 years}

\addplot table [x=Year, y=100 years+, col sep=comma] {./data/index.dat};
\addlegendentry{100 years+}

\end{axis}

\end{tikzpicture}

and it works fine, but I think it's a bit stupid way to do it.

Can I do the same by just specifying that I want to plot all columns from 2 to 7 and use column 1 as x values?

3
  • 1
    I guess this can be done by using some \foreach statements. I'll try if you're so kind to provide a working MWE
    – JMP
    Mar 28, 2016 at 12:59
  • 2
    You've posted a lot of questions and many of them have acceptable answers, but alas, you're not accepting them (at least in most cases :-( ) -- this not how TeX.SX works!
    – user31729
    Mar 28, 2016 at 13:18
  • 1
    Also, please provide a complete (compilable) MWE, not just a snippet, so it's easy for others to copy-paste the provided code.
    – sodd
    Mar 28, 2016 at 13:27

1 Answer 1

3

A Simple Loop

First of all I would read the table once using \pgfplotstableread into a macro and reuse this macro. This speeds up the typesetting and saves you some typing in the case that the location, name, or format of the file changes.

\pgfplotstableread[col sep=comma]{index.dat}\loadedtable

Since you are doing exactly the same thing for each column, viz. plotting and adding the column name to the legend, I would suggest to just loop over all the columns.

\pgfplotsinvokeforeach{0-19 years,20-39 years,40-59 years,60-79 years,80-99 years,100 years+}{
  \addplot table [x=Year, y=#1, col sep=comma] {\loadedtable};
  \addlegendentry{#1}
}

Caution! You have to use either \pgfplotsungroupedforeach or \pgfplotsinvokeforeach here. The classic TikZ \foreach will not work straightforwardly.

You have only provided the first two samples of data, which is why the output looks a little bit ridiculous.

\documentclass{article}
\begin{filecontents*}{index.dat}
Year,0-19 years,20-39 years,40-59 years,60-79 years,80-99 years,100 years+
2000,100,100,100,100,100,100
2001,101,102,101,102,101,102
\end{filecontents*}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
  \begin{axis}[
    width=\textwidth,
    height=0.5\textwidth,
    grid=both,
    xmin=2000,
    xmax=2010,
    xticklabel style={/pgf/number format/1000 sep=, rotate=45},
    ymin=80,
    ]
    \pgfplotstableread[col sep=comma]{index.dat}\loadedtable
    \pgfplotsinvokeforeach{0-19 years,20-39 years,40-59 years,60-79 years,80-99 years,100 years+}{
      \addplot table [x=Year, y=#1] {\loadedtable};
      \addlegendentry{#1}
    }
  \end{axis}
\end{tikzpicture}
\end{document}

enter image description here


More than One Loop Variable

If you additionally want to assign a certain style (color, mark, etc.) to the plots in the loop, you will have to use \foreach, because \pgfplotsinvokeforeach allows only a single variable. The downside is that in contrast to \pgfplotsinvokeforeach, where #1 is simply replaced by the content of the loop variable, for \foreach you have to explicitly expand the loop variable in an \edef context (That is the pitfall with \foreach I was referring to above). The loop hence transforms to

\foreach \col/\style in {%
  0-19 years/{red,dashed,mark options={red}},
  20-39 years/{blue},
  40-59 years/{green},
  60-79 years/{yellow},
  80-99 years/{magenta},
  100 years+/{cyan}
} {
  \edef\temp{%
    \noexpand\addplot+[\style] table [x=Year, y=\col] {\noexpand\loadedtable};
    \noexpand\addlegendentry{\col}
  }
  \temp
}

The full example is then

\documentclass{article}
\begin{filecontents*}{index.dat}
Year,0-19 years,20-39 years,40-59 years,60-79 years,80-99 years,100 years+
2000,100,100,100,100,100,100
2001,101,102,101,102,101,102
\end{filecontents*}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
  \begin{axis}[
    width=\textwidth,
    height=0.5\textwidth,
    grid=both,
    xmin=2000,
    xmax=2010,
    xticklabel style={/pgf/number format/1000 sep=, rotate=45},
    ymin=80,
    ]
    \pgfplotstableread[col sep=comma]{index.dat}\loadedtable
    \foreach \col/\style in {%
      0-19 years/{red,dashed,mark options={red}},
      20-39 years/{blue},
      40-59 years/{green},
      60-79 years/{yellow},
      80-99 years/{magenta},
      100 years+/{cyan}
    } {
      \edef\temp{%
        \noexpand\addplot+[\style] table [x=Year, y=\col] {\noexpand\loadedtable};
        \noexpand\addlegendentry{\col}
      }
      \temp
    }
  \end{axis}
\end{tikzpicture}
\end{document}

enter image description here


Cycle Lists

Another viable alternative (which I would favour) is creating a custom cycle list for colours. In a cycle list, pgfplots picks the next entry automatically on each plot and repeats, when the list has reached its end. To define a cycle list use

\pgfplotscreateplotcyclelist{custom}{%
  red,mark=*\\blue,mark=square*\\green,mark=otimes*\\%
  yellow,mark=star\\magenta,mark=diamond*\\cyan,mark=*\\%
}

The entries in the cycle list are delimited by \\. It is important to hide the linebreak after \\ with a %. In an entry you can specify colours, marks, and other options, such as linestyles. For this example I went with colours and marks. After defining the cycle list (before the axis environment) you have to tell the axis to actually use it by adding cycle list name=custom to the options.

\documentclass{article}
\begin{filecontents*}{index.dat}
Year,0-19 years,20-39 years,40-59 years,60-79 years,80-99 years,100 years+
2000,100,100,100,100,100,100
2001,101,102,101,102,101,102
\end{filecontents*}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
  \pgfplotscreateplotcyclelist{custom}{%
    red,mark=*\\blue,mark=square*\\green,mark=otimes*\\%
    yellow,mark=star\\magenta,mark=diamond*\\cyan,mark=*\\%
  }
  \begin{axis}[
    width=\textwidth,
    height=0.5\textwidth,
    grid=both,
    xmin=2000,
    xmax=2010,
    xticklabel style={/pgf/number format/1000 sep=, rotate=45},
    ymin=80,
    cycle list name=custom
    ]
    \pgfplotstableread[col sep=comma]{index.dat}\loadedtable
    \pgfplotsinvokeforeach{0-19 years,20-39 years,40-59 years,60-79 years,80-99 years,100 years+}{
      \addplot table [x=Year, y=#1] {\loadedtable};
      \addlegendentry{#1}
    }
  \end{axis}
\end{tikzpicture}
\end{document}

enter image description here

2
  • Thanks! That's great. But now I don't have the ability to choose which colors to use. Do you know if it's possible to specify which color mix to use?
    – Jamgreen
    Mar 28, 2016 at 14:24
  • @Jamgreen See updated answer. Mar 28, 2016 at 16:05

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