Ich habe einige Tabellen, die ich lesen und plotten möchte, jede davon in ihrem eigenen Stil. Der Einfachheit halber verwende ich gerne dieselben Tags. Hier ist ein 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}
Kann ich dasselbe Ergebnis mit \pgfplotsforeachinvoke
oder erzielen \foreach
? Etwas wie
\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}
Natürlich könnte ich in diesem einfachen Fall einfach verwenden
\addplot[#1] table[x=x,y=y] {#1.dat};
aber manchmal folgt der Dateiname keinem Muster oder ein anderes Mal möchte ich eine Tabelle nur lesen und speichern, um sie zu ändern oder mehrmals wiederzuverwenden.
Antwort1
Willkommen bei TeX.SE! Eines ist immer möglich:
Schreiben Sie ein Makro, das eine Token-Liste nach Ihren Wünschen zusammenstellt (hier wird eine Reihe von
\addplot
Befehlen mit den entsprechenden Optionen verkettet);dann verwenden Sie ein zweites Makro (in meinem Code aus dem zweiten Argument von erstellt
\foreachTable
), das etwas wie ausgibt\begin{axis}[...]#1\end{axis}
, wobei#1
durch die zuvor zusammengestellte Token-Liste ersetzt wird, die alle\addplot
Befehle enthält.
Diese Technikfunktioniert immer(Nachdem das zweite Makro erweitert wurde, befindet sich der TeX-Eingabestrom in genau demselben Zustand, als hätten Sie den gesamten Code manuell eingegeben.) Sie können es daher verwenden, um Tabellen, Bilder usw. programmgesteuert zu erstellen.
Vollständiger Code:
\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}
Erklärung des Aufrufs:
\foreachTable{tabA, tabB}
{
\begin{axis}[legend, legend pos=south east]
#1
\end{axis}
}
{ \addplot[#1] table[x=x,y=y] {\myTable}; \addlegendentry{#1} }
Das erste Argument ist die Liste der Einträge (jeder Eintrag führt zu einem \addplot
Befehl).
Das zweite Argument ist, was eingefügt wird, nachdem es innen durch die automatisch generierten Befehle #1
ersetzt wurde .\addplot
Das dritte Argument gibt den Code für jedes automatisch generierte Diagramm mit einigen praktischen Ersetzungen an:
#1
ersetzt durch den Eintragsnamen (hier:tabA
danntabB
);\myTable
durch das aus dem Eintragsnamen gebildete Steuersequenz-Token ersetzt (hier:\tabA
für den ersten Eintrag,\tabB
für den zweiten).
Wenn Sie manuell weitere Diagramme hinzufügen möchten (hier eines vor und eines nach den automatisch generierten), können Sie beispielsweise Folgendes tun:
\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} }
Für Menschen, die nicht haben\regex_replace_all:nnN
Wenn Ihr l3kernel
zu alt dafür ist \regex_replace_all:nnN
, können Sie:
füge
\cs_generate_variant:Nn \tl_replace_all:Nnn { Nno }
vorher hinzu\cs_new_protected:Npn \millo_foreach_table_do_axis:nNn #1#2#3
;Ersetzen Sie die Zeile
\regex_replace_all:nnN { \c{myTable} } { \c{##1} } \l_tmpa_tl
mit
\exp_args:NNno \tl_replace_all:Nno \l_tmpa_tl { \myTable } { \use:c {##1} }
Dann sollte es klappenbei dem Zustanddie Sie nicht \myTable
in Klammern verwenden. Verwenden Sie beispielsweise
\foreachTable{tabA, tabB}
{
...
}
{ \addplot[#1] table[x=x,y=y] \myTable; \addlegendentry{#1} }
anstatt:
\foreachTable{tabA, tabB}
{
...
}
{ \addplot[#1] table[x=x,y=y] {\myTable}; \addlegendentry{#1} }