Für Menschen, die nicht haben\regex_replace_all:nnN

Für Menschen, die nicht haben\regex_replace_all:nnN

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 \pgfplotsforeachinvokeoder 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:

  1. Schreiben Sie ein Makro, das eine Token-Liste nach Ihren Wünschen zusammenstellt (hier wird eine Reihe von \addplotBefehlen mit den entsprechenden Optionen verkettet);

  2. 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 #1durch die zuvor zusammengestellte Token-Liste ersetzt wird, die alle \addplotBefehle 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}

Bildschirmfoto

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 \addplotBefehl).

Das zweite Argument ist, was eingefügt wird, nachdem es innen durch die automatisch generierten Befehle #1ersetzt wurde .\addplot

Das dritte Argument gibt den Code für jedes automatisch generierte Diagramm mit einigen praktischen Ersetzungen an:

  • #1ersetzt durch den Eintragsnamen (hier: tabAdann tabB);

  • \myTabledurch das aus dem Eintragsnamen gebildete Steuersequenz-Token ersetzt (hier: \tabAfür den ersten Eintrag, \tabBfü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} }

Bildbeschreibung hier eingeben

Für Menschen, die nicht haben\regex_replace_all:nnN

Wenn Ihr l3kernelzu 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 \myTablein 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} }

verwandte Informationen