[Tex/LaTex] Conditional color and mark style for scatter plot in PGFPlots

groupplotspgfplotspgfplotstabletikz-pgf

I have a data file that has two columns each containing a class, one for color (QoI) and one for marker type (type). I would like points that have have the same QoI value be the same color, but have a different marker type for each type. There are only two different value for type, but several for QoI. I can get the colors working, but cannot figure out how to incorporate different marker styles. I couldn't find a way to use multiple values of meta, but perhaps there's another solution.

There are multiple plots that will be reading from multiple files, though for the MWE below they all read the same data. I just want to make sure the solution also works with groupplots.

MWE

\documentclass[]{standalone}
\usepackage{tikz, pgf, pgfplots, pgfplotstable}
\usepgfplotslibrary{groupplots} % LATEX and plain TEX
\pgfplotsset{compat=1.15}
\usepgfplotslibrary{colorbrewer}
\pgfplotsset{cycle list/Dark2}
\usepackage{filecontents}
\begin{filecontents}{data.dat}
  QoI model surrogate type outname QoI_group error_scaled
  1 -1 -1.01224658575 training Q1 1 0.014956929466
  1 -0.977952092966 -0.984618496392 training Q1 1 0.014956929466
  2 0.53568190987 0.521776331357 training Q2 1 0.0158105026132
  3 0.798208448928 0.789090773894 training Q3 1 0.044540998773
  4 0.378407928561 0.326243792219 training Q4 1 0.0274695358287
  4 0.355049936935 0.33464474407 training Q4 1 0.0274695358287
  3 0.762183505103 0.681415197111 validation Q3 1 0.044540998773
  3 0.822636091166 1.02086372811 validation Q3 1 0.044540998773
\end{filecontents}

\begin{document}
\begin{tikzpicture}[font=\small]
  \tikzset{mark options={mark size=2, opacity=0.5}}
  \begin{groupplot}[group style={group size=3 by 1, horizontal sep=1em},
    width=7cm, height=7cm,
    ymin=-1.2, ymax=1.2, xmin=-1.2, xmax=1.2,
    scatter/classes={1={Dark2-A}, 2={Dark2-B}, 3={Dark2-C}, 4={Dark2-D}},
    scatter,
    scatter src=explicit symbolic,
    ]
    \nextgroupplot[title={1}]
    \addplot[only marks] table[x=model, y=surrogate, meta=QoI] {data.dat};
    \nextgroupplot[title={2}, yticklabels={,,}]
    \addplot[only marks] table[x=model, y=surrogate, meta=QoI] {data.dat};
    \nextgroupplot[title={3}, yticklabels={,,}]
    \addplot[only marks] table[x=model, y=surrogate, meta=QoI] {data.dat};    
  \end{groupplot}
\end{tikzpicture}
\end{document}

Figure generated by MWE

Response to answer addendum

I added some comments to the code below to make more clear what I am trying to achieve. I think I was mistaken, I thought you could "cycle" through colors /based on/ the values of QoI. If that is not the case, do I have to explicitly define the scatter/classes? I could not find an example in the manual, so perhaps that is what is needed.

\documentclass[]{standalone}
\usepackage{tikz, pgf, pgfplots, pgfplotstable}
\usepgfplotslibrary{groupplots} % LATEX and plain TEX
\pgfplotsset{compat=1.15}
\usepgfplotslibrary{colorbrewer}
\usetikzlibrary{plotmarks}
\pgfplotsset{cycle list/Dark2}

\pgfdeclareplotmark{training}{
  \pgfpathcircle{\pgfpoint{0pt}{0pt}}{2pt}\pgfusepathqfillstroke}
\pgfdeclareplotmark{validation}{
  \pgfpathmoveto{\pgfpoint{-2pt}{-1pt}}
  \pgfpathlineto{\pgfpoint{2pt}{-1pt}}
  \pgfpathlineto{\pgfpoint{0pt}{2pt}}
  \pgfpathlineto{\pgfpoint{-2pt}{-1pt}}
  \pgfusepathqfillstroke}
\usepackage{filecontents}
\begin{filecontents}{data.dat}
  QoI model surrogate type outname QoI_group error_scaled
  1 -1 -1.01224658575 training Q1 1 0.014956929466                      % Color 1, mark style 1 (until "type"="validation")
  1 -0.977952092966 -0.984618496392 training Q1 1 0.014956929466        % Color 1
  2 0.53568190987 0.521776331357 training Q2 1 0.0158105026132          % Color 2
  3 0.798208448928 0.789090773894 training Q3 1 0.044540998773          % Color 3
  4 0.378407928561 0.326243792219 training Q4 1 0.0274695358287         % Color 4
  4 0.355049936935 0.33464474407 training Q4 1 0.0274695358287          % Color 4
  3 0.762183505103 0.681415197111 validation Q3 1 0.044540998773        % Color 3, mark style 2
  3 0.822636091166 1.02086372811 validation Q3 1 0.044540998773         % Color 3, mark style 2
\end{filecontents}

\begin{document}
\begin{tikzpicture}[font=\small]
  \tikzset{mark options={mark size=2, opacity=0.5}}
  \begin{groupplot}[group style={group size=3 by 1, horizontal sep=1em},
    width=7cm, height=7cm,
    ymin=-1.2, ymax=1.2, xmin=-1.2, xmax=1.2,
    % Commenting out scatter/classes removes meta color coding.
    % Is there a way that I can automatically cycle the colors in scatter/classes
    % so I don't have to define each explicitly, and so they'll reset for each \addplot+?
    scatter/classes={1={Dark2-A}, 2={Dark2-B}, 3={Dark2-C}, 4={Dark2-D}},
    scatter,
    scatter src=explicit symbolic,
    visualization depends on={value \thisrow{type}  \as \Type},
    visualization depends on={value \thisrow{QoI}  \as \QoI},
    scatter/@pre marker code/.append style={/tikz/mark=\Type},
    % point meta=\coordindex     % This wasn't needed.
    ]
    \nextgroupplot[title={1}]
    \addplot[only marks] table[x=model, y=surrogate, meta=QoI] {data.dat};
    \nextgroupplot[title={2}, yticklabels={,,}]
    \addplot[only marks] table[x=model, y=surrogate, meta=QoI] {data.dat};
    \nextgroupplot[title={3}, yticklabels={,,}]
    \addplot[only marks] table[x=model, y=surrogate, meta=QoI] {data.dat};    
  \end{groupplot}
\end{tikzpicture}
\end{document}

Image from updated code.

Best Answer

An answer inspired by this answer and this answer. You only need to name your symbols somehow and use them like in the example of page 402 of the pgfplots manual. That is, you can use visualization depends on and then change the symbols with scatter/@pre marker code. UPDATE: I dropped the definition of the symbols, which I did for fun (and I stressed that). I do not think that discarding some part of the data and using \addplot over and over is very elegant.

\documentclass[]{standalone}
\usepackage{tikz, pgf, pgfplots, pgfplotstable}
\usepgfplotslibrary{groupplots} % LATEX and plain TEX
\pgfplotsset{compat=1.15}
\usepgfplotslibrary{colorbrewer}
\usetikzlibrary{plotmarks}
\pgfplotsset{colormap/Dark2,
cycle list/Dark2,
    }

\pgfdeclareplotmark{training}{\pgfuseplotmark{*}}
\pgfdeclareplotmark{validation}{\pgfuseplotmark{square}}

\usepackage{filecontents}
\begin{filecontents}{data.dat}
  QoI model surrogate type outname QoI_group error_scaled
  1 -1 -1.01224658575 training Q1 1 0.014956929466                      % Color 1, mark style 1 (until "type"="validation")
  1 -0.977952092966 -0.984618496392 training Q1 1 0.014956929466        % Color 1
  2 0.53568190987 0.521776331357 training Q2 1 0.0158105026132          % Color 2
  3 0.798208448928 0.789090773894 training Q3 1 0.044540998773          % Color 3
  4 0.378407928561 0.326243792219 training Q4 1 0.0274695358287         % Color 4
  4 0.355049936935 0.33464474407 training Q4 1 0.0274695358287          % Color 4
  3 0.762183505103 0.681415197111 validation Q3 1 0.044540998773        % Color 3, mark style 2
  3 0.822636091166 1.02086372811 validation Q3 1 0.044540998773         % Color 3, mark style 2
\end{filecontents}

\begin{document}
\begin{tikzpicture}[font=\small]
  \tikzset{mark options={mark size=2, opacity=0.5}}
  \begin{groupplot}[group style={group size=3 by 1, horizontal sep=1em},
    width=7cm, height=7cm,
    ymin=-1.2, ymax=1.2, xmin=-1.2, xmax=1.2,
    scatter,
    visualization depends on={value \thisrow{type}  \as \Type},
    visualization depends on={value \thisrow{QoI}  \as \QoI},
    scatter/@pre marker code/.append style={/tikz/mark=\Type},
    point meta=explicit
    ]
    \nextgroupplot[title={1}]
    \addplot[only marks] table[x=model, y=surrogate, meta=QoI] {data.dat};
    \nextgroupplot[title={2}, yticklabels={,,}]
    \addplot[only marks] table[x=model, y=surrogate, meta=QoI] {data.dat};
    \nextgroupplot[title={3}, yticklabels={,,}]
    \addplot[only marks] table[x=model, y=surrogate, meta=QoI] {data.dat};    
  \end{groupplot}
\end{tikzpicture}
\end{document}

enter image description here