3

I'd like to make data-dependent plot annotations using pgfplots. For example, the MWE below is a failed attempt at counting the number of points in a scatter plot with y-coordinate greater than 0:

\documentclass[tikz]{standalone}
\usepackage{pgfplots}\pgfplotsset{compat=newest}

\begin{document}

\begin{tikzpicture}
  \begin{axis}[
    xlabel=$x$,
    ylabel=$y$,
  ]
  % a counter for the number of pts w/ y-coord > 0
  \xdef\PtsYGreaterThanZero{0}
  \addplot[
    only marks,
    mark=o,
    blue,
    visualization depends on={y > 0 ? \PtsYGreaterThanZero+1 : \PtsYGreaterThanZero} \as \thisplotcounter,
    nodes near coords={\xdef\PtsYGreaterThanZero{\thisplotcounter}\pgfmathprintnumber{\PtsYGreaterThanZero}},
    ]  coordinates {
           (1,1)
           (2,0)
           (3,1)
           (4,0)
           (5,1) };
    % a data-dependent annotation
    \node[anchor=east,align=left,font=\footnotesize,purple] at (rel axis cs:1,0) {\pgfmathprintnumber{\PtsYGreaterThanZero} points\\greater than 0};
\end{axis}
\end{tikzpicture}

\end{document}

enter image description here

I would like the labels to read 1,1,2,2,3 (a running count of the number of points with y-coordinate > 0), with a final annotation (purple) of "3 points greater than 0"; not the 1,0,1,0,1 and "0 points greater than 0" that appears. The output behaves as if the the original definition of

\PtsYGreaterThanZero

(0) is used for each iteration of plotting points, although to my eye the code reads as if the code segment in "nodes near coords=" of

\xdef\PtsYGreaterThanZero{\thisplotcounter}

could redefine

\PtsYGreaterThanZero

on each iteration to hold an updated cumulative count of the number of points with y-coordinate > 0.

I've tried to get what amounts to a counter across plotted points to work via several different methods---pgfkeys, fancier attempts at re-definition of global macros, use of "scatter/@pre marker code/.code=" and similar entities---all to no avail (they all appeared to almost work except for failing in the same manner as the example above: namely, not updating an original definition of a counter, perhaps due macro definitions not persisting across groups---something I don't understand and don't see in the pgfplots manual).

The bottom line question seems to be this: is it possible to define a macro in pgfplots that can be updated in one point-plotting iteration and available to the next iteration (and also be available at some point after the plotting is completed)?

It seems to me that such a mechanism could be used to make all sorts of automatic data-dependent plot annotations, such as (as another example) finding and labeling extrema of plotted functions (e.g. update a macro that stores extrema values if a currently plotted point possesses a new extreme), but at least one proposed method for finding extrema appears to circumvent any need to explicitly update a value across plotting iterations.

More generally, where can one learn more about what is going on behind the scenes of the pgfplots styles such as

  • point meta
  • nodes near coords
  • visualization depends on
  • execute at begin plot
  • scatter/@pre marker code/.code

and so forth?

3

You can use point meta={TeX code={...}} to do the counting. For nodes near coords the result is expected in \pgfplotspointmeta, so it must be defined in the code. The rest is \pgfmath... stuff.

enter image description here

\documentclass[tikz,border=1mm]{standalone}
\usepackage{pgfplots}\pgfplotsset{compat=newest}

\begin{document}

\begin{tikzpicture}
  \begin{axis}[
    xlabel=$x$,
    ylabel=$y$,
  ]
  % a counter for the number of pts w/ y-coord > 0
  \xdef\PtsYGreaterThanZero{0}
  \addplot[
    only marks,
    mark=o,
    blue,
    point meta={TeX code={\pgfmathparse{ifthenelse(y>0,\PtsYGreaterThanZero+1,\PtsYGreaterThanZero)}%
                    \xdef\PtsYGreaterThanZero{\pgfmathresult}\edef\pgfplotspointmeta{\pgfmathresult}}},
    nodes near coords,
    ]  coordinates {
           (1,1)
           (2,0)
           (3,1)
           (4,0)
           (5,1) };
    % a data-dependent annotation
    \node[anchor=east,align=left,font=\footnotesize,purple] at (rel axis cs:1,0.5) {\pgfmathprintnumber{\PtsYGreaterThanZero} points\\greater than 0};
\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.