如何制作自定义 x 轴范围(从 100 到 0 再到 100)的条形图?
该图应如下所示:
(图为https://doi.org/10.1145/2971648.2971676)
另外,如何使中性条的中间与 0 对齐?
这个答案在某种程度上是接近的,但不能做到上述: 向堆叠条形图中添加单个条形图
答案1
这里我给出一个应该非常接近你要求的解决方案。详情请查看代码中的注释。
% used PGFPlots v1.16
\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
% load PGFPlots ColorBrewer library for adequate colors/an adequate `cycle list'
\usetikzlibrary{
pgfplots.colorbrewer,
}
\pgfplotsset{
% use this `compat' level or higher to use the advanced positioning of
% the axis labels
compat=1.3,
% add the small font size also to the legend entries
small/.append style={
legend style={
font={\small},
},
},
% define a custom style which is used for both `axis' environments
my axis style/.style={
% use the (appended) `small' style
small,
% set axis with and height
width=\axisdefaultwidth,
height=21mm,
% set axis x limits
xmin=-100,
xmax=100,
% use stacked xbars ...
xbar stacked,
% ... where the negative values are plotted separately
stack negative=separate, % <-- default
% align xticks outside ...
xtick align=outside,
% ... and only on the lower axis line
xtick pos=lower,
% don't show yticks
ytick=\empty,
% at x = 0 stuff should be handled differently
extra x ticks={0},
extra x tick style={
xmajorgrids,
grid style={
black,
dashed,
},
xticklabel=\empty,
},
% rotate the ylabel (back)
ylabel style={
rotate=-90,
},
% draw the gridlines on top of the bars
axis on top,
% define the style of the legend
legend style={
at={(0.5,1)},
anchor=south,
yshift=2pt,
legend columns=3,
},
legend cell align=left,
% this loads a proper colormap which contains the colors we want to use
colormap/RdBu-5,
% Now we create the cycle list on our own.
% Because bars are drawn from 0 on, we need to change the order of
% colors of the above loaded `cycle list'; first the 3 negative bars
% and then the 3 positive bars
cycle list={
{index of colormap={2},fill=.,draw=.},
{index of colormap={1},fill=.,draw=.},
{index of colormap={0},fill=.,draw=.},
{index of colormap={2},fill=.,draw=.},
{index of colormap={3},fill=.,draw=.},
{index of colormap={4},fill=.,draw=.},
},
% since we have only one bar per `axis' environment and no y value
% we can state an arbitrary value here
table/y expr=0,
},
}
\begin{document}
\begin{tikzpicture}
% state the values for the different categories
% index 0: strongly disagree
% index 1: disagree
% index 2: (negative) neutral
% index 3: (positive) neutral
% index 4: agree
% index 5: strongly agree
\pgfplotstableread{
0 0 -5 3 56 37
}\TableOne
\pgfplotstableread{
0 -10 -10 8 45 30
}\TableTwo
\begin{axis}[
% load the created style
my axis style,
% misuse the `ylabel'
ylabel={(a)},
% don't show `xticklabels' on the upper plot
xticklabels={},
% list the legend entries
legend entries={
strongly disagree,
disagree,
neutral,, % <-- show neutral only once
agree,
strongly agree%
},
% give the upper `axis' a (node) name
name=upper,
]
% to get the right order of legend entries with the right corresponding
% colors, we need to provide proper `\addlegendimage' commands
\pgfplotsinvokeforeach {0,1,2,0,3,4} {
\addlegendimage{index of colormap={#1},fill=.,draw=.}
}
% now we add the bars in a proper order
\foreach \i in {2,1,0,3,4,5} {
\addplot table [x index=\i] {\TableOne};
}
\end{axis}
\begin{axis}[
my axis style,
% position the "lower" `axis' environment properly, relative to the
% "upper" `axis' environment ...
at={(upper.below south)},
% ... and state a proper `anchor' for the "lower" `axis' environment
anchor=north,
% only show positive values as `xticklabels'
xticklabel={
\pgfmathparse{ifthenelse(\tick < 0, -\tick, \tick)}
\pgfmathprintnumber{\pgfmathresult}
},
xlabel={Percent},
xlabel style={
yshift=2ex,
},
ylabel={(b)},
]
\foreach \i in {2,1,0,3,4,5} {
\addplot table [x index=\i] {\TableTwo};
}
\end{axis}
\end{tikzpicture}
\end{document}