如何生成图表模板

如何生成图表模板

我们大多数人创建的图表必须重复多次,而数据只会发生变化。将 DRY(不要重复自己)编程原则应用于此类问题并非易事。要做到这一点,必须将数据来自推介会。这具有为作者提供更好语义的额外优势,并且可以隐藏pgf和朋友库的冗长内容。它还使图表外观的渐进式编辑变得更容易。

例如考虑下面显示的图表,数据部分由标题、月份标签和两个数据系列组成:

在此处输入图片描述

它们是在如下环境中生成的:

\begin{monthlyChart}
  \addTitle{AHU (October)}
  \addMonth{Oct-11}
  \addPlanned{10}{20}{30}{40}
  \addActual {9}{18}{31}{39}
\end{monthlyChart}

问题

我如何抽象环境的创建,即将原始条形图视为主模板可以从中定义其他变体——而不是重复该过程。例如,为了创建略有不同的图表,我使用了相同的环境,如下所示:

\begin{monthlyChart}
  \addTitle{Turnover $\times 10^3$}
  \addMonth{Jan-11}
  \addPlanned{300}{400}{500}{600}
  \addActual {300}{400}{500}{600}
\end{monthlyChart}

给出的图表现在可以用于其他目的,结果如下:

在此处输入图片描述

我正在寻找一种方法来定义一种createNewChartType命令,它将使用预定义的模板并调整一些参数,更像 Web 开发中使用的模板和主题之间的关系。冗长而冗长的最低限度如下:

\documentclass[12pt]{article}
\usepackage{tikz}
\usetikzlibrary{patterns}
\usepackage{pgfplots}
\makeatletter
\newcommand\progressChart[8]{
  \def\week##1##2{
    \footnotesize
    \begin{tabular}{c}##1\\
        ##2\\\end{tabular}
  }
\begin{tikzpicture}     
  \begin{axis}[
      width=6.9cm,height=5cm,
      bar width=0.3cm,
      title={\ctitle},
      ymin=0,
     % ytick={0,25,50,100,125},
      ylabel=Total,
      ybar=0,symbolic x coords={A, B, C, D}, 
      xtick=data,
      xticklabels={
         \week{\Month}{week-1},
         \week{\Month}{week-2}, 
         \week{\Month}{week-3},
         \week{\Month}{week-4}
      },enlarge x limits=true,
    legend style={
            at={(.43,.98)}, font=\footnotesize }], 
    \addplot[draw=none, fill=gray] coordinates { 
      (A,#1) 
      (B,#2) 
      (C,#3) 
      (D,#4)
     }; 
    \addplot[draw=none,fill=orange!90] coordinates { 
      (A,#5) 
      (B,#6) 
      (C,#7) 
      (D,#8)
      }; 
  \legend{Planned, Actual} 
  \end{axis}   
\end{tikzpicture}}

\newenvironment{monthlyChart}{%
  \def\addMonth##1{\def\Month{##1}}
  \def\addTitle##1{\def\ctitle{\small\textbf{##1}}}
  \def\addPlanned##1##2##3##4{%
  \def\one{##1}\def\two{##2}\def\three{##3}\def\four{##4}}
  \def\addActual##1##2##3##4{%
    \progressChart{\one}{\two}{\three}{\four}{##1}{##2}{##3}{##4}
   }% 
  \parindent0pt}{}
\makeatother
\begin{document}


\begin{monthlyChart}
  \addTitle{AHU (October)}
  \addMonth{Oct-11}
  \addPlanned{10}{20}{30}{40}
  \addActual {9}{18}{31}{39}
\end{monthlyChart}
\begin{monthlyChart}
  \addTitle{AHU (November)}
  \addMonth{Nov-11}
  \addPlanned{30}{40}{50}{60}
  \addActual {30}{40}{60}{60}
\end{monthlyChart}
\begin{monthlyChart}
  \addTitle{AHU (December)}
  \addMonth{Dec-11}
  \addPlanned{30}{40}{50}{60}
  \addActual {30}{50}{58}{70}
\end{monthlyChart}
\begin{monthlyChart}
  \addTitle{AHU (January)}
  \addMonth{Jan-11}
  \addPlanned{30}{40}{50}{60}
  \addActual {30}{40}{50}{113}
\end{monthlyChart}

\begin{monthlyChart}
  \addTitle{Turnover $\times 10^3$}
  \addMonth{Jan-11}
  \addPlanned{300}{400}{500}{600}
  \addActual {300}{400}{500}{600}
\end{monthlyChart}

\end{document}

答案1

有一种方法可以定义主模板,它并不像你想象的那么困难。它叫做自己的风格这也是 pgfplots 如此强大的原因之一。遗憾的是,关于定义自己的样式的部分与其重要性相比太短,因此很容易被忽视(参见pgfplots 手册)让我们看看它是如何工作的:

\pgfplotsset{actual chart bar/.style={draw=none,fill=orange!90}}
\pgfplotsset{planned chart bar/.style={draw=none, fill=gray}}

这里我们定义了实际和计划图表条的样式。如您所见,我们可以在样式名称中使用空格(无需 untexish 驼峰式大小写 ^^)。我们稍后将使用的轴的样式中已完成许多工作。我只会评论我已更改的元素。大部分内容都是从您的示例中逐字逐句提取的。

\pgfplotsset{monthly chart/.style={
    width=6.9cm,height=5cm,
    bar width=0.3cm,
    ymin=0,
    % ytick={0,25,50,100,125},
    ylabel=Total,
    ybar=0,symbolic x coords={W1, W2, W3, W4}, 
    xtick=data,
    xticklabels={
         \week{#1}{week-1},
         \week{#1}{week-2},
         \week{#1}{week-3},
         \week{#1}{week-4}
    },

我将符号坐标更改为 W1、W2、W3 和 W4,因为我们将在主文档中使用它们,我认为这样更易读。命令\week与您的相同。这里重要的一点是 #1它应该是月份(例如 11 月),并且每个图都不同,因此我们不能使用常数。我们稍后会看到这#1将如何成为实际月份。

    x tick label style={font=\footnotesize},

在这里我们改变 xticks 标签的字体大小。

    enlarge x limits=true,
    legend style={at={(.43,.98)}, font=\footnotesize },
    cycle list={
        planned chart bar,
        actual chart bar
    },

循环列表将定义单个绘图的样式,即第一个绘图采用计划的图表条样式,第二个绘图采用实际的图表条样式。

    legend entries={Planned, Actual},

我们已经可以在这里定义图例,如果您需要另一个特殊图表的订单,您可以在此图表中覆盖此设置。

    title style={font=\small\bfseries}
}}

我们只定义标题的样式。标题本身在具体图表中设置。

现在我们可以在主文档中对每个月度图表使用该样式:

\begin{tikzpicture}
    \begin{axis}[monthly chart=Oct-11, title={AHU (October)}]
        \addplot coordinates {(W1,10) (W2,20) (W3,30) (W4,40)};
        \addplot coordinates {(W1,9) (W2,18) (W3,31) (W4,39)};
    \end{axis}
\end{tikzpicture}

标题的设置方式与在任何普通 pgfplot 中设置的方式相同。一般来说,对于以前使用过 pgfplots 的每个人来说,这看起来都非常熟悉。这里唯一的新奇之处是月度图表样式。现在我们还看到了如何 #1用所需的月份/文本替换。这种方法比您的新环境稍微冗长一些,但它非常灵活且易读。

例如,直接插入第三个数据集:

\begin{tikzpicture}
    \begin{axis}[monthly chart=Nov-11, title={AHU (November)}]
        \addplot[planned chart bar] coordinates {(W1,14) (W2,20) (W3,50) (W4,60)};
        \addplot[draw=none, fill=green] coordinates {(W1,11) (W2, 22) (W3,33) (W4,43)};
        \addplot[actual chart bar] coordinates {(W1,15) (W2,21) (W3,60) (W4,60)};
        \legend{Planned,Ideal,Actual}
    \end{axis}
\end{tikzpicture}

或者如果需要改变图例位置:

\begin{tikzpicture}
    \begin{axis}[monthly chart=Dec-11, title={AHU (December)}, legend style={at={(.95,.98)}}]
        \addplot coordinates {(W1,65) (W2,40) (W3,40) (W4,36)};
        \addplot coordinates {(W1,75) (W2,58) (W3,50) (W4,30)};
    \end{axis}
\end{tikzpicture}

或者更改 ylabel:

\begin{tikzpicture}
    \begin{axis}[monthly chart=Jan-11, title={AHU (January)}, ylabel=Sold Apples]
        \addplot coordinates {(W1,30) (W2,40) (W3,50) (W4,60)};
        \addplot coordinates {(W1,30) (W2,40) (W3,50) (W4,113)};
    \end{axis}
\end{tikzpicture}

在此处输入图片描述

完整代码如下:

\documentclass[12pt]{article}
\usepackage{tikz}
\usetikzlibrary{patterns}
\usepackage{pgfplots}

\def\week#1#2{
    \begin{tabular}{c}#1\\
    #2\\\end{tabular}
    }

\pgfplotsset{actual chart bar/.style={draw=none,fill=orange!90}}
\pgfplotsset{planned chart bar/.style={draw=none, fill=gray}}

\pgfplotsset{monthly chart/.style={
        width=6.9cm,height=5cm,
        bar width=0.3cm,
        ymin=0,
        % ytick={0,25,50,100,125},
        ylabel=Total,
        ybar=0,symbolic x coords={W1, W2, W3, W4}, 
        xtick=data,
        xticklabels={
            \week{#1}{week-1},
            \week{#1}{week-2},
            \week{#1}{week-3},
            \week{#1}{week-4}
        },
        x tick label style={font=\footnotesize},
        enlarge x limits=true,
        legend style={at={(.43,.98)}, font=\footnotesize },
        cycle list={
            planned chart bar,
            actual chart bar
        },
        legend entries={Planned, Actual},
        title style={font=\small\bfseries}
    }
}

\begin{document}
\noindent
\begin{tikzpicture}
    \begin{axis}[monthly chart=Oct-11, title={AHU (October)}]
        \addplot coordinates {(W1,10) (W2,20) (W3,30) (W4,40)};
        \addplot coordinates {(W1,9) (W2,18) (W3,31) (W4,39)};
    \end{axis}
\end{tikzpicture}
\begin{tikzpicture}
    \begin{axis}[monthly chart=Nov-11, title={AHU (November)}]
        \addplot[planned chart bar] coordinates {(W1,14) (W2,20) (W3,50) (W4,60)};
        \addplot[draw=none, fill=green] coordinates {(W1,11) (W2, 22) (W3,33) (W4,43)};
        \addplot[actual chart bar] coordinates {(W1,15) (W2,21) (W3,60) (W4,60)};
        \legend{Planned,Ideal,Actual}
    \end{axis}
\end{tikzpicture}
\begin{tikzpicture}
    \begin{axis}[monthly chart=Dec-11, title={AHU (December)}, legend style={at={(.95,.98)}}]
        \addplot coordinates {(W1,65) (W2,40) (W3,40) (W4,36)};
        \addplot coordinates {(W1,75) (W2,58) (W3,50) (W4,30)};
    \end{axis}
\end{tikzpicture}
\begin{tikzpicture}
    \begin{axis}[monthly chart=Jan-11, title={AHU (January)}, ylabel=Sold Apples]
        \addplot coordinates {(W1,30) (W2,40) (W3,50) (W4,60)};
        \addplot coordinates {(W1,30) (W2,40) (W3,50) (W4,113)};
    \end{axis}
\end{tikzpicture}
\end{document}

相关内容