3

I would like to use PGFPlots to create a plot using three sets of metadata. I figure it would be best to have one set represented by the plot mark and the remaining two by the fill and draw colour respectively. However, I am only able to the mark and one colour:

\documentclass[10pt,a4paper,landscape]{article}
\usepackage{pgfplots}   


\begin{document}


\begin{tikzpicture}
\begin{axis}

\addplot[
only marks,
scatter,
point meta = \thisrow{C1},
visualization depends on = {value \thisrow{Mark} \as \markshape},
visualization depends on = { \thisrow{C2} \as \col2},
    scatter/@pre marker code/.append style = {
            /tikz/draw = \col2,
            /tikz/mark = \markshape
            }
]
table[x=X,y=Y, row sep = \\]{
    X   Y   C1  C2  Mark \\
    1   1   0   6   *   \\
    2   2   6   0   otimes* \\
    3   1   0   0   square* \\
    4   5   6   6   diamond*    \\
};

\end{axis}
\end{tikzpicture}

\end{document}

enter image description here

The row C2 has no effect on the plot whereas Mark, implemented in the same way, does. Having looked into the manual and corresponding forum entries, I have not been able to find a solution for this problem.

In addition, in my real data, all metadata is in the form of strings and I would, preferably, have something like the scatter classes, which translates a predefined string to a visualization style, e.g. "abc" to "fill = red" or to "mark = \otimes*", depending on the row.

Although I could code every combination of metadata as a seperate scatter class to get what I want, that would be very time consuming and I hope that you can help me getting PGFPlots to do the work for me.

  • Welcome to TeX.SX! You can have a look at our starter guide to familiarize yourself further with our format. – mvkorpel Jun 27 '14 at 8:27
2

The following code solves the plotting problem for tables like the one in your example. The solution applies \addplot twice for each point: once for the fill and another time for the draw colour.

\documentclass[10pt,a4paper,landscape]{article}
\usepackage{pgfplots}


\begin{document}


\begin{tikzpicture}
\begin{axis}

  \pgfplotstableread[row sep = \\]{
    X   Y   C1  C2  Mark \\
    1   1   0   6   *   \\
    2   2   6   0   otimes* \\
    3   1   0   0   square* \\
    4   5   6   6   diamond*    \\
  }\thetable
  \pgfplotstablegetrowsof{\thetable}
  \pgfmathsetmacro{\rowsminus}{\pgfplotsretval-1}

  \foreach \i in {0,...,\rowsminus} {

    \pgfplotstablegetelem{\i}{X}\of\thetable
    \pgfmathsetmacro{\x}{\pgfplotsretval}
    \pgfplotstablegetelem{\i}{Y}\of\thetable
    \pgfmathsetmacro{\y}{\pgfplotsretval}
    \pgfplotstablegetelem{\i}{C1}\of\thetable
    \pgfmathsetmacro{\fillcolor}{\pgfplotsretval}
    \pgfplotstablegetelem{\i}{C2}\of\thetable
    \pgfmathsetmacro{\drawcolor}{\pgfplotsretval}
    \pgfplotstablegetelem{\i}{Mark}\of\thetable
    \edef\mymarkshape{\pgfplotsretval}

    \addplot[
    scatter,
    point meta = \fillcolor,
    visualization depends on = {value \mymarkshape \as \markshape},
    scatter/use mapped color = {color=mapped color, draw opacity=0},
    scatter/@pre marker code/.append style = {/tikz/mark = \markshape},
    ] coordinates {
      (\x,\y)
    };

    \addplot[
    scatter,
    point meta = \drawcolor,
    visualization depends on = {value \mymarkshape \as \markshape},
    scatter/use mapped color = {color=mapped color, fill opacity=0},
    scatter/@pre marker code/.append style = {/tikz/mark = \markshape},
    ] coordinates {
      (\x,\y)
    };
  }

\end{axis}
\end{tikzpicture}

\end{document}

Picture produced by example code

The following example code might help you solve the other part of the question, if I understood what you are after. The code accepts metadata in another format: a string consisting of comma-separated "visualization classes" in column Meta. Each class only affects one aspect of style (fill color, drawing color, or plot mark), but it would be easy to define more complex classes. If the style of some point should be left at the default settings, an unknown class name such as default can be used as the Meta value of the point.

I used the following sources of information:

\documentclass[10pt,a4paper,landscape]{article}
\usepackage{pgfplots}
\usepackage{etoolbox}
\usepackage{xstring}


\begin{document}

% Handler for metadata, ignores unknown strings
\newcommand{\mymetahandler}[1]{%
  \IfStrEqCase{#1}{%
    {A}{\pgfmathsetmacro{\fillcolor}{0}}%
    {B}{\pgfmathsetmacro{\fillcolor}{6}}%
    {a}{\pgfmathsetmacro{\drawcolor}{0}}%
    {b}{\pgfmathsetmacro{\drawcolor}{6}}%
    {aa}{\edef\mymarkshape{*}}%
    {bb}{\edef\mymarkshape{otimes*}}%
    {cc}{\edef\mymarkshape{square*}}%
    {dd}{\edef\mymarkshape{diamond*}}%
  }
}

\begin{tikzpicture}
\begin{axis}

  \pgfplotstableread[row sep = \\]{
    X   Y   Meta   \\
    1   1   A,b,aa \\
    2   2   B,a,bb \\
    3   1   A,a,cc \\
    4   5   B,b,dd \\
  }\thetable
  \pgfplotstablegetrowsof{\thetable}
  \pgfmathsetmacro{\rowsminus}{\pgfplotsretval-1}

  \foreach \i in {0,...,\rowsminus} {

    \pgfplotstablegetelem{\i}{X}\of\thetable
    \pgfmathsetmacro{\x}{\pgfplotsretval}
    \pgfplotstablegetelem{\i}{Y}\of\thetable
    \pgfmathsetmacro{\y}{\pgfplotsretval}

    % Default point style
    \pgfmathsetmacro{\fillcolor}{0}
    \pgfmathsetmacro{\drawcolor}{0}
    \edef\mymarkshape{*}

    % Call the handler for each comma-separated metadata item
    \pgfplotstablegetelem{\i}{Meta}\of\thetable
    \expandafter\forcsvlist\expandafter\mymetahandler\expandafter{\pgfplotsretval}

    \addplot[
    scatter,
    point meta = \fillcolor,
    visualization depends on = {value \mymarkshape \as \markshape},
    scatter/use mapped color = {color=mapped color, draw opacity=0},
    scatter/@pre marker code/.append style = {/tikz/mark = \markshape},
    ] coordinates {
      (\x,\y)
    };

    \addplot[
    scatter,
    point meta = \drawcolor,
    visualization depends on = {value \mymarkshape \as \markshape},
    scatter/use mapped color = {color=mapped color, fill opacity=0},
    scatter/@pre marker code/.append style = {/tikz/mark = \markshape},
    ] coordinates {
      (\x,\y)
    };
  }

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