How to plot scatter points using pgfplots with color defined from table rgb values?

I am trying to plot a set of data points (scatter points not linked to each other), where each point has a different color. The color definition is given by predefined rgb values written in the same file that contains the data.

The following file serves as example:

\usepackage{filecontents}
\begin{filecontents}{test.dat}
x   y   RED   GREEN   BLUE
1   11  0.2    0.3    0.5
2   14  0.3    0.3    0.4
4   26  0.1    0.8    0.1
3   39  0.0    0.1    0.9
\end{filecontents}


The x and y columns represent the position of the points I want to plot. The next three columns RED, GREEN and BLUE correspond to the associated color values in rgb format.

What I was trying so far, was to do:

\begin{document}

\pgfplotstableread{test.dat}\test
%number of points to be plotted
\pgfplotstablegetrowsof{\test}
\pgfmathsetmacro{\N}{\pgfplotsretval-1}

\begin{tikzpicture}
\begin{axis}[%
xmin=0, xmax=5,
ymin=0, ymax=45,
width=8cm,
height=6cm,
grid=both,
xlabel=Xtest,
ylabel=Ytest,
]
\foreach \i in {0,...,\N}
{
\definecolor{testcolor}{rgb}{\thisrow{3}, \thisrow{4}, \thisrow{5}}
\addplot[scatter,
only marks,
scatter/use mapped color={draw=none,fill=testcolor},
]
table [x index = 0,y index = 1]{\test};
}
\end{axis}
\end{tikzpicture}

\end{document}


But I am unable to fetch a single row value for the color definition. How can I do this ? I also looked at meta options, but the color is defined with a single value (linearly) and I need the three components in the color definition.

• ugly alternative but if you're able to read only columns, you could try to write your *.dat file the following way: x | y | RED1 | GREEN1 | BLUE1 | RED2 | GREEN2 etc. where x and y are columns of n elements, but RED1, GREEN1 etc are columns of only 1 element... This would result in a file with 3*n+2 rows, but it might be better than nothing! Aug 21, 2014 at 6:04
• @anderstood In this case I guess I would also need to split x and y as x1 | y1 | RED1 | GREEN1 | BLUE1 | x2 | y2 | ... It's not really what I'm looking for. There has to be a way to read the table row by row... Aug 21, 2014 at 14:18

1 Answer

While it is possible to access table elements by means of \pgfplotstablegetelem{0}{RED}\of{\test}, I would recommend to move the code which defines colors into the \addplot command: pgfplots supports advanced scatter plots in which you can define how each scatter point it is to be drawn. This is more efficient in TeX.

A solution could be

\documentclass{standalone}

\usepackage{pgfplots}

\pgfplotsset{compat=1.9}

\begin{document}

\begin{tikzpicture}
\begin{axis}[%
xmin=0, xmax=5,
ymin=0, ymax=45,
width=8cm,
height=6cm,
grid=both,
xlabel=Xtest,
ylabel=Ytest,
]
\addplot[
scatter,%
scatter/@pre marker code/.code={%
\edef\temp{\noexpand\definecolor{mapped color}{rgb}{\pgfplotspointmeta}}%
\temp
\scope[draw=mapped color!80!black,fill=mapped color]%
},%
scatter/@post marker code/.code={%
\endscope
},%
only marks,
mark=*,
point meta={TeX code symbolic={%
\edef\pgfplotspointmeta{\thisrow{RED},\thisrow{GREEN},\thisrow{BLUE}}%
}},
]
table {
x   y   RED   GREEN   BLUE
1   11  0.2    0.3    0.5
2   14  0.3    0.3    0.4
4   26  0.1    0.8    0.1
3   39  0.0    0.1    0.9
};
\end{axis}
\end{tikzpicture}
\end{document}


I used \addplot table {<inline data>}; to reduce the amount of code (which is, however, equivalent to \addplot ... table {\test};). The key points are:

• I added mark=* since scatter does not necessarily assign a plot mark as default.
• I used the keys pre marker code and post marker code to define the colors. This is precisely the same way how the default scatter implementation works. In our case, I used \definecolor{rgb}{\pgfplotspointmeta}, assuming that \pgfplotspointmeta contains something of sorts <R>,<G>,<B>.
• Finally, the complicated point meta expression defines \pgfplotspointmeta in the expected way.
• Note that we cannot simply insert \thisrow{RED},... into \definecolor here: \thisrow is only valid while pgfplots iterates over the table's row - and it does that just once when it surveys the input coordinates.
• The macro \edef means "expanded definition": \edef\temp{...} defines \temp to contain the expanded argument. \noexpand means to not expand the following macro in this context.
• point meta={TeX code symbolic={<code which defines \pgfplotspointmeta}} allows us to inject some TeX code to define a symbol - in our case a color triplet.
• Thanks for the detailed answer and explanations. It worked smoothly ! Aug 24, 2014 at 13:46
• It seems that using \addplot ... table {\test}; returns an error (missing number, treated as zero <to be read again> t). I included the table as in the OP and loaded \pgfplotstableread{test.dat}{\data}, see hastebin.com/yafimoziru.tex. I must say I see no reason for this. Oct 3, 2015 at 18:30
• I'm also getting the same "missing number, ..." error when loading from a file. Any suggestions please? Jul 14, 2019 at 13:11