我有一张包含许多实例结果的大表,我想制作按一个(或多个)字段分组的单独表格和图表。在这个最小工作示例中,我想为所有 20 个房屋实例制作一个表格和一个图表,为所有 200 个房屋实例制作另一个表格和图表。
最好的办法是从原始表格中获取两个子表格,只保留 houses=20 或 houses=200 的行(如果我可以在表格文件中分离数据,我就会得到这样的行)。我希望避免每次排版表格或绘图时都明确过滤,或者至少应该使用最少的代码来执行此操作(也许定义自定义样式?)。
\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\usepackage{pgfplotstable}
\begin{document}
\pgfplotstableread{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
}{\fulltable}
Table for all instances
\pgfplotstabletypeset{\fulltable}
\begin{tikzpicture}
\begin{axis}[
title={Values for all instances},
xlabel={Instance},
ylabel={Value}]
\addplot+[scatter, only marks] table[x=instance, y=value]
{\fulltable};
\end{axis}
\end{tikzpicture}
\newpage
Table for 20 houses instances
???
Plot for 20 houses instances
???
\end{document}
编辑
通过查看类似的问题,我想出了这个部分解决方案:
%\filtertable{table}{field}{value}{#1}
\newcommand{\filtertable}[4]{
\pgfplotstablegetelem{#4}{#2}\of{#1}
\ifnum\pgfplotsretval=#3\relax
\else\pgfplotstableuserowfalse\fi
}
%\filtertableplot{table}{field}{value}
\newcommand{\filtertableplot}[3]{
\pgfplotstablegetelem{\coordindex}{#2}\of{#1}
\ifnum\pgfplotsretval=#3
\else
\def\pgfmathresult{}
\fi
}
Table for 200 houses instances
\pgfplotstabletypeset[
columns={instance,value},
row predicate/.code={\filtertable{\fulltable}{houses}{200}{#1}}
]
{\fulltable}
\begin{tikzpicture}
\begin{axis}[
title={Values for 200 houses instances},
xlabel={Instance},
ylabel={Value},
x filter/.code={\filtertableplot{\fulltable}{houses}{200}{#1}}]
\addplot+[scatter, only marks] table[x=instance, y=value]
{\fulltable};
\end{axis}
\end{tikzpicture}
有没有办法避免重复表名,避免明确使用#1
,并将x filter=...
和包装row predicate=...
在样式中?
答案1
您可以使用以下方式过滤要绘制的值discard if not={<column name>}{<value>}
您可以使用以下键当条形图基于符号值时,是否可以更改单个条形的颜色?. 这允许您输入
\addplot+[only marks, discard if not={houses}{20}] table[x=instance, y=value]
{fulltable.dat};
houses
仅绘制值为 的条目20
。为此,您需要将以下代码块放入前言中,并绘制文件中的数据(而不是使用 创建的表中的数据\pgfplotstableread
)。
\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
}
}
}
对于表格,您可以执行类似操作(尽管代码有点棘手)。它允许您键入
\pgfplotstabletypeset[discard if not={houses}{20}]{fulltable.dat}
过滤行。
\makeatletter
\pgfplotstableset{
discard if not/.style 2 args={
row predicate/.code={
\def\pgfplotstable@loc@TMPd{\pgfplotstablegetelem{##1}{#1}\of}
\expandafter\pgfplotstable@loc@TMPd\pgfplotstablename
\edef\tempa{\pgfplotsretval}
\edef\tempb{#2}
\ifx\tempa\tempb
\else
\pgfplotstableuserowfalse
\fi
}
}
}
\makeatother
\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\usepackage{pgfplotstable}
\usepackage{filecontents}
\begin{document}
\pgfplotstableread{
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
}{\fulltable}
\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}
\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
}
}
}
\makeatletter
\pgfplotstableset{
discard if not/.style 2 args={
row predicate/.code={
\def\pgfplotstable@loc@TMPd{\pgfplotstablegetelem{##1}{#1}\of}
\expandafter\pgfplotstable@loc@TMPd\pgfplotstablename
\edef\tempa{\pgfplotsretval}
\edef\tempb{#2}
\ifx\tempa\tempb
\else
\pgfplotstableuserowfalse
\fi
}
}
}
\makeatother
\centering
{\bfseries Table for 20 houses instances:}
\pgfplotstabletypeset[discard if not={houses}{20}]{fulltable.dat}
\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}
\end{document}
答案2
最简单的答案是利用 /pgfplots/boxplot/data filter/.code={} 选项。请参阅 pgfplots 手册第 501 页。您可以尝试 \addplot table[only if={entry of houses is 20}]{fulltable.dat};