3

I have a tikz barplot which I want as a \newcommand with a variable. Depending on the variable, labels should be added or not. In the document I will use the plot several times, sometimes with, sometimes without labels. Thats why I want it as a command.

here my MWE:

\documentclass{article}
\usepackage{tikz, pgfplots}
\begin{document}

\newcommand{\myplotWithoutLabels}{
\begin{tikzpicture}
\begin{axis}[xbar, bar shift=0pt, bar width=20pt, xmin=0,
axis x line = none, axis y line* = middle, 
ytick={1,2,3}, tickwidth=0, every tick/.style={draw=none},% label pos, no   tick marks
yticklabels={}
]
\addplot coordinates {(2,1)};
\addplot coordinates {(5,2)};
\addplot coordinates {(4,3)};
\end{axis}
\end{tikzpicture}
}

\myplotWithoutLabels

\newcommand{\myplotWithLabels}{
\begin{tikzpicture}
\begin{axis}[xbar, bar shift=0pt, bar width=20pt, xmin=0,
axis x line = none, axis y line* = middle, 
ytick={1,2,3}, tickwidth=0, every tick/.style={draw=none},
yticklabels={L1, L2, L3}
]
\addplot coordinates {(2,1)};
\addplot coordinates {(5,2)};
\addplot coordinates {(4,3)};
\end{axis}
\end{tikzpicture}
}

\myplotWithLabels
\end{document}    

I've tried several things, i.e.:

\newcommand{\myplot}[3]{
\begin{tikzpicture}
\begin{axis}[title=my Title,
xbar, bar shift=0pt, bar width=20pt, xmin=0,
axis x line = none, axis y line* = middle,
ytick={1,2,3}, tickwidth=0, every tick/.style={draw=none},
yticklabels={#1, #3, #3}
]
\addplot coordinates {(2,1)};
\addplot coordinates {(5,2)};
\addplot coordinates {(4,3)};
\end{axis}
\end{tikzpicture}
}

\myplot[L1,L2,L3]

or with only one (#1) argument. Neither did work.

The solution to this question Problem declaring newcommand with tikzpicture inside didn't help me either.

EDIT:
Thanks for the comments and answers. Now the \newcommand works. However, there is one problem left. The plot generated with the \newcommand with argument is slightly shifted up on the y axis.

Here the code, I've put the two plots next to each other using subcaption package (\usepackage{subcaption}) to see the difference. The plots are both as \newcommand, one without argument, one with argument.

\newcommand{\myplot}[1]{
\begin{tikzpicture}
\begin{axis}[
xbar, bar shift=0pt, bar width=20pt, xmin=0,
axis x line = none, axis y line* = middle,
ytick={1,2,3}, tickwidth=0, every tick/.style={draw=none},
yticklabels={#1}
]
\addplot coordinates {(2,1)};
\addplot coordinates {(5,2)};
\addplot coordinates {(4,3)};
\end{axis}
\end{tikzpicture}
}

\begin{figure}[h!]
\centering
\begin{subfigure}[h!]{0.45\textwidth}
\myplotWithoutLabels
\end{subfigure}
\begin{subfigure}[h!]{0.45\textwidth}
\myplot{}
\end{subfigure}
\end{figure}

plots next to each other

I can't find the reason for the shift.

4
  • It should be yticklabels={#1,#2,#3} and \myplot{L1}{L2}{L3}. Or declare \myplot to have a single argument, coding yticklabels{#1}; then the call \myplot{L1,L2,L3} would be good.
    – egreg
    Mar 1, 2017 at 18:18
  • 1
    To see how \newcommand works, consider reading How to create new commands with multiple arguments?
    – Werner
    Mar 1, 2017 at 19:03
  • 1
    What egreg said works, for the version without label just write \myplot{}{}{}.
    – CarLaTeX
    Mar 1, 2017 at 20:57
  • How is \myplotWithoutLabels defined? You don't want h! as the placement option for figure, but you really, really, really don't want it for subfigure where it makes no sense at all.
    – cfr
    Mar 3, 2017 at 1:25

2 Answers 2

10

You have two choices; which one depends very much on the application.

Remember that if you do

\newcommand{\foo}[3]{...}

then a call to \foo should be of the form

\foo{first}{second}{third}

where each argument is braced. It's not the same as in other programming language: the syntax \foo{first,second,third} would take first,second,third as #1 and TeX would look further for #2 and #3.

\documentclass{article}
\usepackage{tikz, pgfplots}

\newcommand{\myplotA}[3]{%
  \begin{tikzpicture}
  \begin{axis}[
    xbar,
    bar shift=0pt,
    bar width=20pt,
    xmin=0,
    axis x line = none,
    axis y line* = middle, 
    ytick={1,2,3},
    tickwidth=0,
    every tick/.style={draw=none},% label pos, no   tick marks
    yticklabels={#1,#2,#3},
  ]
  \addplot coordinates {(2,1)};
  \addplot coordinates {(5,2)};
  \addplot coordinates {(4,3)};
  \end{axis}
  \end{tikzpicture}%
}

\newcommand{\myplotB}[1]{%
  \begin{tikzpicture}
  \begin{axis}[
    xbar,
    bar shift=0pt,
    bar width=20pt,
    xmin=0,
    axis x line = none,
    axis y line* = middle, 
    ytick={1,2,3},
    tickwidth=0,
    every tick/.style={draw=none},% label pos, no   tick marks
    yticklabels={#1},
  ]
  \addplot coordinates {(2,1)};
  \addplot coordinates {(5,2)};
  \addplot coordinates {(4,3)};
  \end{axis}
  \end{tikzpicture}%
}

\begin{document}

\myplotA{L1}{L2}{L3}

\bigskip

\myplotB{L1,L2,L3}

\end{document}    

As you see in the picture, the output is the same.

enter image description here

1
  • I now realise that my code is identical to yours and that the only difference between yours and that in the OP's edit is that the OP removed your comment signs which I then put back. Not only is it an egreg answer, it is egreg's answer. Do you want to add some explanation and I delete mine?
    – cfr
    Mar 3, 2017 at 1:46
2

This is really an egreg answer, because egreg specialises in this ;).

Your definition introduces spurious spaces because you have not commented line endings which TeX interprets as spaces.

I don't know how your second definition is done, so I adapted your first to take an optional, rather than mandatory argument:

\documentclass{article}
\usepackage{subcaption,pgfplots}
\newcommand*{\myplot}[1][]{
  \begin{tikzpicture}
    \begin{axis}[
      xbar,
      bar shift=0pt,
      bar width=20pt,
      xmin=0,
      axis x line = none,
      axis y line* = middle,
      ytick={1,2,3},
      tickwidth=0,
      every tick/.style={draw=none},
      yticklabels={#1}
      ]
      \addplot coordinates {(2,1)};
      \addplot coordinates {(5,2)};
      \addplot coordinates {(4,3)};
    \end{axis}
  \end{tikzpicture}
}
\begin{document}
\begin{figure}[h!]
  \centering
  \begin{subfigure}{0.45\textwidth}
    \myplot
  \end{subfigure}
  \begin{subfigure}{0.45\textwidth}
    \myplot[L1,L2,L3]
  \end{subfigure}
\end{figure}
\end{document}

This reproduces the issue:

misaligned plots

Removing the spurious spaces fixes the issue.

aligned plots

\documentclass{article}
\usepackage{subcaption,pgfplots}
\newcommand*{\myplot}[1][]{%
  \begin{tikzpicture}
    \begin{axis}[
      xbar,
      bar shift=0pt,
      bar width=20pt,
      xmin=0,
      axis x line = none,
      axis y line* = middle,
      ytick={1,2,3},
      tickwidth=0,
      every tick/.style={draw=none},
      yticklabels={#1}
      ]
      \addplot coordinates {(2,1)};
      \addplot coordinates {(5,2)};
      \addplot coordinates {(4,3)};
    \end{axis}
  \end{tikzpicture}%
}
\begin{document}
\begin{figure}[h!]
  \centering
  \begin{subfigure}{0.45\textwidth}
    \myplot
  \end{subfigure}
  \begin{subfigure}{0.45\textwidth}
    \myplot[L1,L2,L3]
  \end{subfigure}
\end{figure}
\end{document}

Note that I have removed the h! specifier from the subfigures because it makes no sense there and is not even defined, as far as I know. subfigure takes the same placement specifiers as minipage according to the manual.

I have not removed it from figure because it is defined there. However, you certainly should not use it. It never makes sense to give only h as the location specifier. If you really don't want the figure to more, don't use a float.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .