堆叠条形图/组图,x 坐标上有文本标签

堆叠条形图/组图,x 坐标上有文本标签

我试图堆叠一个组图,或者将堆叠的图分组?但是我试图得到类似这样的结果:

在此处输入图片描述

这个ybar stacked选项在这里效果很好。但是当我尝试将其调整为组图时,我遇到了一些问题。目标是创建三个组,每个组都有一个xlabel。在每个组中,每个条形图也应该有自己的xticklabel。到目前为止,MWE 给出了这个

在此处输入图片描述

为什么前三个堆叠部分之后会有分离?我如何才能分别标记条形图,同时标记组?

这个groupplot命令是否是解决这个“问题”的正确命令?

梅威瑟:

\documentclass{article}
\usepackage{tikz}
\usepackage{pgfplots,pgfplotstable}
\usetikzlibrary{pgfplots.groupplots}
\pgfplotsset{width=0.3\textwidth,compat=newest}

\pgfplotstableread{
cr  Fii Faa Foo
abc 10  20  30
def 5   5   5
ghi 7   7   7
jkl 1.5 1.5 2.5
mno 2   2   2
pqrs    0   0   8
tuv 0   0   1.16
wxyz    0   5   0
}\first

\pgfplotstableread{
cr  Fii Faa Foo
abc 7   7   12.9
def 7.5 7.5 7.5
ghi 8   8   8
jkl 1.5 1.5 2.25
mno 2   2   2
pqrs    0   0   8
tuv 0   0   1.544
wxyz    0   6.3 0
}\second

\pgfplotstableread{
cr  Fii Faa Foo
abc 7   7   19
def 7.5 7.5 7.5
ghi 9   9   9
jkl 1.5 1.5 2.25
mno 2   2   2
pqrs    0   0   8
tuv 0   0   23
wxyz    0   8.4 0
}\third

\pgfplotsset{
    select row/.style={
        x filter/.code={\ifnum\coordindex=#1\else\def\pgfmathresult{}\fi}
    }
}

\begin{document}

\begin{figure}[hbt!]
\centering
\begin{tikzpicture}
\begin{groupplot}
    [
        group style=
            {columns=3,
             ylabels at=edge left,
             group name=plots},
        ybar stacked,
        scale only axis,
        ylabel=y-axis,
        ymin=0,
        ymax=150,
        height=0.5\textwidth,
        xtick=\empty,
    legend columns=-1,
    legend image code/.code={%
         \draw[#1] (0cm,-0.1cm) rectangle (0.3cm,0.1cm);
        }
    ]

\nextgroupplot[xlabel=Item 1, legend to name=grouplegend,]
\pgfplotsinvokeforeach  {0,...,7}{
    \addplot table [x expr=\coordindex, select row=#1, y=Fii] {\first};
    \addplot table [x expr=\coordindex, select row=#1, y=Faa] {\first};
    \addplot table [x expr=\coordindex, select row=#1, y=Foo] {\first};
    \addlegendentry {\pgfplotstablegetelem{#1}{cr}\of \first \pgfplotsretval}
}

\nextgroupplot[xlabel=Item 2]
\pgfplotsinvokeforeach  {0,...,7}{
    \addplot table [x expr=\coordindex, select row=#1, y=Fii] {\second};
    \addplot table [x expr=\coordindex, select row=#1, y=Faa] {\second};
    \addplot table [x expr=\coordindex, select row=#1, y=Foo] {\second};
}

\nextgroupplot[xlabel=Item 3]
\pgfplotsinvokeforeach  {0,...,7}{
    \addplot table [x expr=\coordindex, select row=#1, y=Fii] {\third};
    \addplot table [x expr=\coordindex, select row=#1, y=Faa] {\third};
    \addplot table [x expr=\coordindex, select row=#1, y=Foo] {\third};
}

\end{groupplot}
\node at (plots c2r1.north) [inner sep=0pt,anchor=south,yshift=3ex] {\ref{grouplegend}};
\end{tikzpicture}
\end{figure}

\end{document}

答案1

我认为这是一个有趣的情节。所以我将提供我的答案。

回答您的一些问题:

  1. groupplot 命令是否是解决这个“问题”的正确命令?
    是的,这样groupplot做只是让它们以一种更简单的方式并排放置。不多也不少。每个都\nextgroupplot实际上与封闭环境相同axis

  2. 为什么前三个堆叠部分之后会有分离?
    因为您有x expr=\coordindex。这意味着在第二个循环中,\pgfplotsinvokeforeachx expr=1第三个循环中x expr=2。这意味着一个新列。如果您尝试注释掉ymax=80000,您就会明白我的意思。

  3. 我怎样才能分别标记各个条形图,并将其中三个条形图标记到一个站点?
    我不太明白您的问题,但我认为我的答案对此有一个解决方案,否则请回复。

如何让它工作

首先,你的数据应该重新排列。你的X坐标应在第一列,然后每个站点(美国广播公司定义,...) 应为一个新列。
这样您就可以更轻松地处理数据,而无需使用那些烦人的过滤器(如果您可以在没有过滤器的情况下工作,通常会更容易)。

因此您的数据必须采用以下格式:

\pgfplotstableread{
Criterion    abc   def   ghi   jkl   mno  pqrs    tuv  wxyz 
Komp        7000  7500  7500  1500  2000     0      0     0 
Komp+PV     7000  7500  7500  1500  2000     0      0  5000 
Sorp       12000  7500  7500  2250  2000  8000  11600     0 
}\Rapperswil

完成后你需要告诉pgfplots使用标准X-tickmarks。这需要使用键:xticklabels from table={\Rapperswil}{Criterion}xtick=data。因此,您不需要预先输入X-数据!

最终结果变成:

\documentclass{article}
\usepackage{pgfplots,pgfplotstable}
\pgfplotstableread{
Criterion    abc   def   ghi   jkl   mno  pqrs    tuv  wxyz 
Komp        7000  7500  7500  1500  2000     0      0     0 
Komp+PV     7000  7500  7500  1500  2000     0      0  5000 
Sorp       12000  7500  7500  2250  2000  8000  11600     0 
}\Rapperswil

\begin{document}
\begin{tikzpicture}
  \begin{axis}[ybar=0pt,
    ybar stacked,bar shift=0pt,
    xticklabels from table={\Rapperswil}{Criterion},
    xtick=data,
    legend style={at={(1.025,1.0)},anchor=north west},
    xlabel=Rapperswil]
    \pgfplotstableforeachcolumn\Rapperswil\as\col{%
        \ifnum\pgfplotstablecol=0 
        \else
        \edef\tmp{%
            \noexpand\addplot table [x expr=\noexpand\coordindex,y=\col] {\noexpand\Rapperswil};
            \noexpand\addlegendentry {\col}%
        }%
        \tmp
        \fi
    }
  \end{axis}
\end{tikzpicture}
\end{document}

请注意,您需要\edef由于\pgfplotstableforeachcolumn在循环退出时未完全展开而导致的。

代码输出

群图

当您需要将其与 放在一起时,groupplots您的代码是正确的,但是请使用y descriptions at=edge left而不是ylabels at=edge left。前者会在 上同时制作标签和勾选edge left。而后者仅适用于ylabels

使用的示例groupplots是执行以下操作。如果不确定该键的作用,请查阅手册。我添加了第二个表格。我将把它保留为简单的练习添加最后一个!

\documentclass{article}
\usepackage{pgfplots,pgfplotstable}
\usetikzlibrary{pgfplots.groupplots}
\pgfplotstableread{
Criterion    abc   def   ghi   jkl   mno  pqrs    tuv  wxyz 
Komp        7000  7500  7500  1500  2000     0      0     0 
Komp+PV     7000  7500  7500  1500  2000     0      0  5000 
Sorp       12000  7500  7500  2250  2000  8000  11600     0 
}\Rapperswil
\pgfplotstableread{
Criterion    abc   def   ghi   jkl   mno  pqrs    tuv  wxyz 
Komp        7000  7500  8000  1500  2000     0      0     0 
Komp+PV     7000  7500  8000  1500  2000     0      0  6300 
Sorp       12900  7500  8000  2250  2000  8000  15440     0 
}\Palermo

\begin{document}
\begin{tikzpicture}
  \begin{groupplot}[group style= {
        columns=2,xlabels at=edge bottom,
        y descriptions at=edge left,
        horizontal sep=0cm,group name=plots,
    },
    ymin=0,ymax=6e4,enlarge x limits={abs=.5},
    ybar,ybar stacked,
    /pgf/bar shift=0pt,/pgf/bar width=1.5cm,
    xlabel style={yshift=-2ex}, % make the xlabel further down from the ticks
    xticklabels from table={\Rapperswil}{Criterion}, % use the ticklabels from the table as a tick mark
    xtick=data,legend columns=1]
    % This defines a new axis environment which will be filled with data from table \Rapperswil
    \nextgroupplot[xlabel=Rapperswil,legend to name=grouplegend]
    \pgfplotstableforeachcolumn\Rapperswil\as\col{%
        \ifnum\pgfplotstablecol=0 % The first column is "Criterion" we do not need that one, skip
        \else
        \edef\tmp{%
            \noexpand\addplot table [x expr=\noexpand\coordindex,y=\col] {\noexpand\Rapperswil};
            \noexpand\addlegendentry {\col}%
        }%
        \tmp
        \fi
    }
    % This defines a new axis environment which will be filled with data from table \Palermo
    \nextgroupplot[xlabel=Palermo]
    \pgfplotstableforeachcolumn\Palermo\as\col{%
        \ifnum\pgfplotstablecol=0 
        \else
        \edef\tmp{%
            \noexpand\addplot table [x expr=\noexpand\coordindex,y=\col] {\noexpand\Palermo};
        }%
        \tmp
        \fi
    }
  \end{groupplot}
  % Draw the dashed lines below the plot
  \draw[dashed] (plots c1r1.south west) -- ++(0,-1.5);
  \draw[dashed] (plots c2r1.south west) -- ++(0,-1.5);
  \draw[dashed] (plots c2r1.south east) -- ++(0,-1.5);
  % This will make the legend at the right of the plot just like Excel
  \node at (plots c2r1.east) [inner sep=0pt,anchor=west, xshift=.6cm] {\ref{grouplegend}};
\end{tikzpicture}

\end{document}

相关内容