# filter pgfplots data more than once (e.g. with discard if)

I want to filter a dat file more than once (i.e., filter on multiple columns), and the usual solution with "discard if" and "discard if not" doesn't seem to work.

I.e., the following (were file.dat has a column called k) should have empty output, and it doesn't.

\addplot[discard if not={k}{3}, discard if={k}{3}]
table [x=A,  y=B]
{file.dat};


Here is an MWE, including the alternative discard if code given in one of the answers.

 \documentclass[12pt]{article}%
% \usepackage{amsmath,amsthm,amssymb,graphicx,array,tabularx,url,enumerate,rotating,fancyvrb,longtable, units,mathabx}%
\usepackage{pgfplots}
\usepackage{pgfplotstable}

\pgfplotsset{
discard if/.style 2 args={
x filter/.code={
\edef\tempa{\thisrow{#1}}
\edef\tempb{#2}
\ifx\tempa\tempb
\def\pgfmathresult{inf}
\fi
}
},
discard if not/.style 2 args={
x filter/.code={
\edef\tempa{\thisrow{#1}}
\edef\tempb{#2}
\ifx\tempa\tempb
\else
\def\pgfmathresult{inf}
\fi
}
}
}

% \pgfplotsset{
%     discard if/.style 2 args={
%         x filter/.code={
%             \ifnum\thisrow{#1}=#2
%                 \def\pgfmathresult{nan}
%             \else
%             \fi
%         }
%     }
%   }
% \pgfplotsset{
%     discard if not/.style 2 args={
%         x filter/.code={
%             \ifnum\thisrow{#1}=#2
%             \else
%                 \def\pgfmathresult{nan}
%             \fi
%         }
%     }
%   }

\begin{document}

\begin{tikzpicture}
\begin{axis}
\addplot[blue,mark=o,discard if not={k}{3}, discard if={k}{3}] table [x=n,  y=A]{    n A k

1 3 3
2 4 3
3 2 3
1 3 2
1 3 2
1 3 2
};
\end{axis}
\end{tikzpicture}

\begin{tikzpicture}
\begin{axis}
n A k
1 3 3
2 4 3
3 2 3
1 3 2
1 3 2
1 3 2
};
\end{axis}
\end{tikzpicture}

\begin{tikzpicture}
\begin{axis}
n A k
1 3 3
2 4 3
3 2 3
1 3 2
1 3 2
1 3 2
};
\end{axis}
\end{tikzpicture}
\end{document}


Output:

Is there a way to apply multiple filters in pgfplots or should I just cut the .dat files up a little more before-hand?

You can filter the data more than once by adapting the code (which was originally posted in an answer to Is it possible to change the color of a single bar when the bar plot is based on symbolic values? and Different color for individual bar in bar chart & adding bar labels) slightly, using x filter/.append code instead of x filter/.code:

For filtering on a symbolic column:

\pgfplotsset{
discard if/.style 2 args={
x filter/.append code={
\edef\tempa{\thisrow{#1}}
\edef\tempb{#2}
\ifx\tempa\tempb
\def\pgfmathresult{inf}
\fi
}
},
discard if not/.style 2 args={
x filter/.append code={
\edef\tempa{\thisrow{#1}}
\edef\tempb{#2}
\ifx\tempa\tempb
\else
\def\pgfmathresult{inf}
\fi
}
}
}


For filtering on a numerical column:

\pgfplotsset{
discard if/.style 2 args={
x filter/.append code={
\ifdim\thisrow{#1} pt=#2pt
\def\pgfmathresult{inf}
\fi
}
},
discard if not/.style 2 args={
x filter/.append code={
\ifdim\thisrow{#1} pt=#2pt
\else
\def\pgfmathresult{inf}
\fi
}
}
}

• aha! I have been using this one in another file but I thought the tempa and tempb were part of a tex.se MWE so I didn't test it. Will try it out now. – Alejandro Apr 1 '16 at 18:02
• This didn't work when I tested it, so I updated (in 5 min) the question with the MWE – Alejandro Apr 1 '16 at 23:15
• @Alejandro: To filter on numerical data, you should use a slightly different variant of discard if and discard if not. I've edited my answer. – Jake Apr 2 '16 at 7:52
• Perfect. It was the .append that was needed. First part works for my "numerical" data too (I don't know how LaTeX is interpreting it). – Alejandro Apr 2 '16 at 8:24

For certain plots, such as hist (for histograms), using x filter doesn't work as expected. This is because x filter (and y filter etc.) are applied to the resulting intervals, after the data has been counted. To filter this sort of data, one can use y expr and unbounded coords=discard.

For numeric:

\addplot[hist,
unbounded coords=discard,% nan means ignore
filter discard warning=false,% no spam
] table [
y expr={\thisrow{k} == 3 ? \thisrow{A} : nan}
] {file.dat};


For symbolic (need a helper macro from this answer):

\makeatletter
\newcommand{\strequal}[2]{\pdf@strcmp{#1}{#2}==0}
\makeatother


Also, y filter etc. operate pretty late in the process, after any transformations such as applying log scaling, so one should use rawy in filters or use the y expr method above if you are directly filtering y values.