2

I would like to build several Pareto diagram figures using a \newcommand, like this:

\documentclass[11pt]{amsart}
\usepackage{pgfplots}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{xfp}
\definecolor{Azul}{rgb}{0.16, 0.32, 0.75}

\newcommand{\GraficoPareto}[9]{ \begin{tikzpicture} \draw (0,0) rectangle (10,5); \foreach \i/\j in {0/#6,2/#7,4/#8,6/#9,8/,10/}{ \draw (\i,2pt) -- (\i,-2pt) node[below] { \j }; } \foreach \i in {0,1,...,5}{ \ifnum\i>0 \draw[densely dashed,gray] (-.1,\i) -- (10.1,\i) node[right] {\textcolor{black}{$\fpeval{20\i}%$}}; \else \node[right,gray] (Texto) at (10.1,\i) {\textcolor{black}{$\fpeval{20\i}%$}}; \fi \node[left] (Te) at (-0.1,\i) {$\fpeval{8\i}$}; } \fill[Azul!100!black,opacity=0.8] (0.02,0) rectangle ({2-0.02},{#15/40}); \fill[Azul!100!black,opacity=0.8] (2.02,0) rectangle ({4-0.02},{#25/40}); \fill[Azul!100!black,opacity=0.8] (4.02,0) rectangle ({6-0.02},{#35/40}); \fill[Azul!100!black,opacity=0.8] (6.02,0) rectangle ({8-0.02},{#45/40}); \fill[Azul!100!black,opacity=0.8] (8.02,0) rectangle ({10-0.02},{#55/40}); \draw[line width=3pt,orange] (1,{5(#1/50)}) -- (3,{5((#1+#2)/50)}) -- (5,{5((#1+#2+#3)/50)}) -- (7,{5((#1+#2+#3+#4)/50)}) -- (9,{5*((#1+#2+#3+#4+#5)/50)}); \node (Legendax) at (5,-1) {Soma das horas}; \node (Legenday) at (-1,2.5) {\rotatebox{90}{Frequência}}; \end{tikzpicture} }

\begin{document}

\GraficoPareto{30}{10}{5}{3}{2}{94}{194}{294}{394}

\end{document}

Whose result is this:

enter image description here

However, I would like to insert more two parameters (then 11), where I can to define the final x-labels. But this does not work.

How can I define this figure using 11 parameters?

CarLaTeX
  • 62,716
  • 4
    Simple answer is don’t. Pass a single argument with tikz key value pairs instead. – Alan Munn Feb 12 '22 at 21:30
  • tex syntax only allows #1 to #9 but theuser interface even with 9 is very hard to use and hard to read use eithr a key val list as Alan suggests or ifthe values really are a list and you wantto treat them all the same, use a comma list in a single argument – David Carlisle Feb 12 '22 at 21:43
  • Could you like to give and example? – Angelo Aliano Filho Feb 12 '22 at 21:52
  • Olá, @AngeloAlianoFilho. You may check some options in More than 9 argument. You may also check xparse and other methods do deal with multiple inputs. On the other hand, I would consider some way to insert your data as a list of numbers as here. Therefore 1 input has all needed data. I'd also think about creating a style file to keep the model save apart the main file. – FHZ Feb 12 '22 at 22:23
  • 1
    By using multiple argument grabbing steps you can grab an arbitrary amount of tokens, but as others already said, why bother, either use a key=value syntax, or use a single argument which is a list. – Skillmon Feb 12 '22 at 23:31
  • Agreed with @Skillmon. Since each data point is simply a number, I would pass a comma separated list and parse with listofitems https://ctan.org/pkg/listofitems?lang=en or process with Lua – likethevegetable Feb 13 '22 at 14:56
  • If you absolutely want this and if "x-labels" means the phrases "Soma das horas" and "Frequência", then instead of having \GraficoPareto carry out \node (Legendax) at (5,-1) {Soma das horas}; \node (Legenday) at (-1,2.5) {\rotatebox{90}{Frequência}}; \end{tikzpicture} have \GraficoPareto call another macro which takes two arguments and does \node (Legendax) at (5,-1) {#1}; \node (Legenday) at (-1,2.5) {\rotatebox{90}{#2}}; \end{tikzpicture} and call the unextendible argument-monster as \GraficoPareto{30}{10}{5}{3}{2}{94}{194}{294}{394}{Soma das horas}{Frequência}. – Ulrich Diez Feb 14 '22 at 12:25

2 Answers2

6

I suggested a list based approach. This answer is part of it. The idea is to use one single input of the newcommand syntax as broad as possible. Your original idea is not extendable (you cannot add more and more inputs as you need), this is a major flaw since I may guess you want to extend (expand) for more and more data.

This answer is based on:

  1. Pareto diagram in LaTeX
  2. Draw Pareto chart with pgfplots?
  3. https://www.ctan.org/pkg/pgfplots
  4. pgfplots: two axis for one dataset e.g. °C and °F
  5. Distance between bars with pgfplot

I created a newcommand with two inputs as the coordinates for the command addplot formated by axis.

I suggest you to learn about pgfplots, it is an amazing tool. I'm not an expert, there might be better methods to achieve the results you want.

Please note, my answer doesn't compute the frequencies (Frequência) instead I just present the cumulated sum (Acumulado) manually inserted in the second input argument. There are however a few options:

  • Use any math tool or computer code to write down both lists for you;
  • Learn how to do the math directly in TikZ (Sorry, I don't know this trick for coordinates);
  • Check references from links 4 and 5 to learn how to create tables with your data or external files.

The MWE is:

\documentclass{article}

\usepackage{pgfplots}

\newcommand{\myPareto}[2]{ \begin{tikzpicture} \begin{axis}[ ylabel={Acumulado}, xlabel={Soma das horas}, ymin=0, xtick=data, axis y line*=left, ymajorgrids, major y grid style={dashed, thick} ] \addplot[ybar interval, fill=blue, opacity=0.5] coordinates {#1}; \addplot[draw, mark=*, orange, ultra thick] coordinates {#2};
\end{axis} \begin{axis}[ axis y line=right, axis x line=none, yticklabel={\pgfmathparse{100\tick}\pgfmathprintnumber[fixed,precision=0]\pgfmathresult%}, ymin=0, ]
\end{axis} \end{tikzpicture} }

\begin{document} \myPareto{(94,30) (194,10) (294,5) (394,3) (494,2) (594,0)} {(144,30) (244,40) (344,45) (444,48) (544,50)} \end{document}

I added mark=* to show the coordinates of second input. The result is presented below.

enter image description here

FHZ
  • 3,939
  • By "expandable", do you mean "extendable"? As in, able to easily add more points? Just that "expandable" has a very particular meaning in TeX so should probably be only used to mean TeX's interpretation. – Andrew Stacey Feb 13 '22 at 11:35
  • Oh, I see. Totally misuse of terms of myself. I corrected the terminology. Thanks. – FHZ Feb 13 '22 at 16:52
5

I wouldn't construct such (monster of) \newcommand. Rather use a table, where are collected data for diagrams. Such approach, according to my opinion, is more clear and flexible (you can simply extend the table with more rows and columns). Beside this, such MWE is better understandable to others, which will be eventually interested for your code (for example, if you will use it articles for journals):

\documentclass[margin=3.141592]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}

\pgfplotstableread{ X1 y1 X2 y2 94 30 144 30 194 10 244 40 294 5 344 45 394 3 444 48 494 2 544 50 594 0 nan nan }{\datatable}

\begin{document} \begin{tikzpicture} \begin{axis}[ ymajorgrids, major y grid style={dashed}, ylabel={Acumulado}, xtick=data, xlabel={Soma das horas}, ymin=0, ] \addplot [ybar interval, fill=blue, semitransparent] table [x=X1, y=y1] {\datatable}; \addplot [orange, very thick, mark=*] table [x=X2, y=y2] {\datatable}; \end{axis} \begin{axis}[ axis y line=right, axis x line=none, yticklabel={\pgfmathparse{int(round(100\tick))}% \pgfmathresult% }, ymin=0, ] \end{axis} \end{tikzpicture} \end{document}

enter image description here

Zarko
  • 296,517