我有一些想要閱讀和繪製的表格,每個表格都有自己的風格。為了方便起見,我喜歡使用相同的標籤。這是一個 MWE:
\documentclass{minimal}
\usepackage{pgfplotstable}
\begin{filecontents}{tabA.dat}
x y
0 0
1 1
2 2
3 3
\end{filecontents}
\begin{filecontents}{tabB.dat}
x y
0 1
1 2
2 3
3 4
\end{filecontents}
\pgfplotsset{compat=newest,
tabA/.style={color=red,mark=*},
tabB/.style={color=black,mark=o},
}
\pgfplotstableread{tabA.dat}\tabA
\pgfplotstableread{tabB.dat}\tabB
\begin{document}
\begin{tikzpicture}
\begin{axis}[legend,legend pos=south east]
\addplot[tabA] table[x=x,y=y] {\tabA};\label{pgf:tabA}\addlegendentry{tabA}
\addplot[tabB] table[x=x,y=y] {\tabB};\label{pgf:tabB}\addlegendentry{tabB}
\end{axis}
\end{tikzpicture}
\end{document}
\pgfplotsforeachinvoke
我可以使用or達到相同的結果嗎\foreach
?就像是
\begin{tikzpicture}
\begin{axis}[legend,legend pos=south east]
\pgfplotsinvokeforeach{tabA,tabB}{%
% The following doesn't work, of course
\addplot[#1] table[x=x,y=y] {\#1}; % <- Magic goes here
}
\end{axis}
\end{tikzpicture}
當然,在這個簡單的情況下我可以簡單地使用
\addplot[#1] table[x=x,y=y] {#1.dat};
但有時檔案的名稱不遵循某種模式,或者有時我只想讀取和儲存表以便修改它或重複使用它多次。
答案1
歡迎來到 TeX.SE!一件事總是可能的:
編寫一個巨集,以您想要的方式組裝令牌清單(此處,將一系列
\addplot
命令與適當的選項連接起來);然後使用第二個巨集(在我的程式碼中,由 的第二個參數建構
\foreachTable
)輸出類似 的內容\begin{axis}[...]#1\end{axis}
,並#1
替換為包含所有\addplot
命令的先前組裝的標記清單。
這種技術總是有效(展開第二個巨集後,TeX 輸入流的狀態與您手動輸入所有代碼的狀態完全相同)。因此,您可以使用它以程式設計方式產生表格、圖片等您想要的任何內容。
完整程式碼:
\begin{filecontents}{tabA.dat}
x y
0 0
1 1
2 2
3 3
\end{filecontents}
\begin{filecontents}{tabB.dat}
x y
0 1
1 2
2 3
3 4
\end{filecontents}
\documentclass[tikz, border=2mm]{standalone}
\usepackage{xparse}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\ExplSyntaxOn
\seq_new:N \l__millo_plot_cmds_tl
\cs_new_protected:Npn \millo_foreach_table_do_axis:nNn #1#2#3
{
\tl_clear:N \l__millo_plot_cmds_tl
\clist_map_inline:nn {#1}
{
\tl_set:Nn \l_tmpa_tl {#3}
\regex_replace_all:nnN { \c{myTable} } { \c{##1} } \l_tmpa_tl
\tl_put_right:NV \l__millo_plot_cmds_tl \l_tmpa_tl
}
\exp_args:No #2 \l__millo_plot_cmds_tl
}
\NewDocumentCommand \foreachTable { m m m }
{
\cs_set_protected:Npn \__millo_axis_func:n ##1 {#2}
\millo_foreach_table_do_axis:nNn {#1} \__millo_axis_func:n {#3}
}
\ExplSyntaxOff
\pgfplotsset{
tabA/.style={color=red,mark=*},
tabB/.style={color=black,mark=o},
}
\pgfplotstableread{tabA.dat}\tabA
\pgfplotstableread{tabB.dat}\tabB
\begin{document}
\begin{tikzpicture}
\foreachTable{tabA, tabB}
{
\begin{axis}[legend, legend pos=south east]
#1
\end{axis}
}
{ \addplot[#1] table[x=x,y=y] {\myTable}; \addlegendentry{#1} }
\end{tikzpicture}
\end{document}
調用說明:
\foreachTable{tabA, tabB}
{
\begin{axis}[legend, legend pos=south east]
#1
\end{axis}
}
{ \addplot[#1] table[x=x,y=y] {\myTable}; \addlegendentry{#1} }
第一個參數是條目清單(每個條目指向一個\addplot
指令)。
#1
第二個參數是內部被自動產生的指令取代後將插入的內容\addplot
。
第三個參數指定每個自動產生的繪圖的程式碼,以及一些方便的替換:
#1
替換為條目名稱(此處:tabA
thentabB
);\myTable
替換為根據條目名稱建構的控制序列標記(此處:\tabA
對於第一個條目,\tabB
對於第二個條目)。
如果您想手動新增更多繪圖(此處為自動產生的繪圖之前一張和之後一張),您可以執行以下操作:
\foreachTable{tabA, tabB}
{
\begin{axis}[legend, legend pos=south east]
\addplot {sin(deg(\x))}; \addlegendentry{$\sin$}
#1
\addplot {sqrt(\x)}; \addlegendentry{$x\mapsto \sqrt{x}$}
\end{axis}
}
{ \addplot[#1] table[x=x,y=y] {\myTable}; \addlegendentry{#1} }
對於沒有的人\regex_replace_all:nnN
如果您l3kernel
太老了,無法擁有\regex_replace_all:nnN
,您可以:
添加
\cs_generate_variant:Nn \tl_replace_all:Nnn { Nno }
在之前\cs_new_protected:Npn \millo_foreach_table_do_axis:nNn #1#2#3
;更換線路
\regex_replace_all:nnN { \c{myTable} } { \c{##1} } \l_tmpa_tl
和
\exp_args:NNno \tl_replace_all:Nno \l_tmpa_tl { \myTable } { \use:c {##1} }
然後它應該可以工作在條件下您不使用\myTable
內部大括號。例如,使用
\foreachTable{tabA, tabB}
{
...
}
{ \addplot[#1] table[x=x,y=y] \myTable; \addlegendentry{#1} }
代替:
\foreachTable{tabA, tabB}
{
...
}
{ \addplot[#1] table[x=x,y=y] {\myTable}; \addlegendentry{#1} }