总结

总结

众所周知这个答案,可以使用discard if notstyle/filter 从表中过滤行。但此解决方案仅在提供文件名作为 的参数时才有效,如果使用 读取表并将其用作参数,则\addplot table它将不起作用:\pgfplotstableread{file}\name\addplot[discard if not...] table \name;

不

\documentclass{standalone}

\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\usepackage{pgfplotstable}
\usepackage{filecontents}


\begin{filecontents}{fulltable.dat}
houses  instance    value
20      1           8919
20      2           8965
20      3           8901
20      4           8816
20      5           8875
20      6           9027
20      7           8915
20      8           8907
20      9           8832
20      10          8934
200     1           84714
200     3           85630
200     4           84748
200     5           84565
200     6           85109
200     7           84588
200     8           84638
200     9           84673
200     10          85170
\end{filecontents}


\begin{document}

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

\pgfplotstableread{fulltable.dat}\fulltable

\begin{tikzpicture}[trim axis left]
  \begin{axis}[
      title={{\bfseries Plot for 20 houses instances}},
      xlabel={Instance},
      ylabel={Value}]
    \addplot+[only marks, discard if not={houses}{20}] table[x=instance, y=value]
      {fulltable.dat};
  \end{axis}
\end{tikzpicture}

\begin{tikzpicture}[trim axis left]
  \begin{axis}[
      title={{\bfseries Plot for 20 houses instances}},
      xlabel={Instance},
      ylabel={Value}]
    \addplot+[only marks, discard if not={houses}{20}] table[x=instance, y=value]
      {\fulltable};
  \end{axis}
\end{tikzpicture}

\end{document}

该怎么办?我希望这个东西能用于宏。

答案1

总结

以下工作

\def\thisrowunavailableloadtabledirectly{thisrow_unavailable_load_table_directly}
\def\sudogetthisrow#1#2{
    \edef#2{\thisrow{#1}}
    \ifx#2\thisrowunavailableloadtabledirectly % if \thisrow fails to get the element
                            % then #2 is thisrow_unavailable_load_table_directlye
                            % we have a backup
        \getthisrow{#1}{}
        \let#2=\pgfplotsretval
    \fi
}

\pgfplotsset{
    discard if not/.style 2 args={
        x filter/.code={
            \sudogetthisrow{#1}\tempa
            \edef\tempb{#2}
            \ifnum\tempa=\tempb
            \else
                \def\pgfmathresult{inf}
            \fi
            \message{^^J\tempa,\tempb,\pgfmathresult^^J}
        }
    }
}

故事

当从宏读取表格时,pgfplots 将执行宏\pgfplots@addplotimpl@table@fromstructure@。在这种情况下\thisrow,和\thisrowno不起作用。因此,pgfplotscoordprocessing.code.tex作者在 6522-6529 行添加了一些注释

% These macros are-unfortunately- not accessable here. And the
% worst is: error messages are impossible either because they are
% not executed... try to provide useful hints:
\def\thisrow##1{thisrow_unavailable_load_table_directly}%
\def\thisrowno##1{thisrowno_unavailable_load_table_directly}%
% this should work.
\def\getthisrow##1##2{\pgfplotstablegetelem{\coordindex}{##1}\of{#3}{##2}}%
\def\getthisrowno##1##2{\pgfplotstablegetelem{\coordindex}{[index]##1}\of{#3}{##2}}%
%

看起来作者建议我们应该使用\getthisrow{houses}\tempa

但是如果你尝试这样做,你会得到另一个错误。原因是\pgfplotstablegetelem只接受三个参数。因此{##2}(将是\tempa)将被留在外面,并且不可避免地会发出undefined control sequence

所以这里的技巧是定义一个须藤getthisrow 版本

  • 尝试通过以下方式获取元素\edef\tempa{\thisrow{houses}}
  • 如果失败,请尝试\getthisrow{houses}{}(注意空参数)
    • \pgfplotstablegetelem将存储元素到\pgfplotsretval
    • 放手tempa\pgfplotsretval

完整工作代码

\documentclass{standalone}

\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\usepackage{pgfplotstable}
\usepackage{filecontents}


\begin{filecontents}{fulltable.dat}
houses  instance    value
20      1           8919
20      2           8965
20      3           8901
20      4           8816
20      5           8875
20      6           9027
20      7           8915
20      8           8907
20      9           8832
20      10          8934
200     1           84714
200     3           85630
200     4           84748
200     5           84565
200     6           85109
200     7           84588
200     8           84638
200     9           84673
200     10          85170
\end{filecontents}


\begin{document}

\def\thisrowunavailableloadtabledirectly{thisrow_unavailable_load_table_directly}
\def\sudogetthisrow#1#2{
    \edef#2{\thisrow{#1}}
    \ifx#2\thisrowunavailableloadtabledirectly % if \thisrow fails to get the element
                            % then #2 is thisrow_unavailable_load_table_directlye
                            % we have a backup
        \getthisrow{#1}{}
        \let#2=\pgfplotsretval
    \fi
}

\pgfplotsset{
    discard if not/.style 2 args={
        x filter/.code={
            \sudogetthisrow{#1}\tempa
            \edef\tempb{#2}
            \ifnum\tempa=\tempb
            \else
                \def\pgfmathresult{inf}
            \fi
            \message{^^J\tempa,\tempb,\pgfmathresult^^J}
        }
    }
}

\pgfplotstableread{fulltable.dat}\fulltable

\begin{tikzpicture}[trim axis left]
  \begin{axis}[
      title={{\bfseries Plot for 20 houses instances}},
      xlabel={Instance},
      ylabel={Value}]
    \addplot+[only marks, discard if not={houses}{20}] table[x=instance, y=value]
      {fulltable.dat};
  \end{axis}
\end{tikzpicture}

\begin{tikzpicture}[trim axis left]
  \begin{axis}[
      title={{\bfseries Plot for 20 houses instances}},
      xlabel={Instance},
      ylabel={Value}]
    \addplot+[only marks, discard if not={houses}{20}] table[x=instance, y=value]
      {\fulltable};
  \end{axis}
\end{tikzpicture}

\end{document}

相关内容