如何制作表示间隔的条形图?

如何制作表示间隔的条形图?

我想制作按类别分组的项目的条形图(见下面的草图)。每个类别可以由图例中指定的数据类型的任意组合组成。我想从表中读取所有数据,但我不确定某种“单元格数组”或“结构”是否更好。

在此处输入图片描述

我已经尝试使用bchart以下包在这里回答(但发生了我无法隐藏 y 轴的情况):

\documentclass{standalone}
\usepackage{bchart}
\usetikzlibrary{patterns}

% Bars:
\newcommand{\bccbar}[3][]{
    % Set defaults:
    \renewcommand{\bcbarcolor}{blue!20}
    \renewcommand{\bcbartext}{}
    \renewcommand{\bcbarlabel}{}
    \renewcommand{\bcbarvalue}{#2\bcunit--#3\bcunit}
    \renewcommand{\bcplainbar}{false}
    % Read parameters:
    \setkeys{bcbar}{#1}
    % Draw bar:
    \draw [pattern=crosshatch dots]
          ([xshift=(#2-\bcmin)*(\bcwidth/\bcrange)]0,\bcpos) coordinate (tlbar) rectangle
          ([xshift=(#3-\bcmin)*(\bcwidth/\bcrange)]0,\bcpos-5mm) coordinate (brbar);
    \ifthenelse{\equal{\bcplainbar}{true}}{}{
        % Write value:
        \node [fill=white,inner sep=1.5pt,anchor=west] at ($(tlbar-|brbar)!0.5!(brbar)$) {\bcfontstyle{\bcbarvalue, \bcbartext}};
    }
    % Write text:
    %\node[anchor=west] at ([xshift=#3*(\bcwidth/\bcrange)]0,\bcpos-2.5mm) {\bcfontstyle\bcbartext};
    % Write label:
    %\node[anchor=east] at ([xshift=#2*(\bcwidth/\bcrange)]0,\bcpos-2.5mm) {\bcfontstyle\bcbarlabel};
    % Move vertical position downward:
    \addtolength{\bcpos}{-5mm}
}%

\begin{document}
\begin{bchart}[min=-10,max=100,step=10]
\bccbar[text=A]{20}{45}
\smallskip
\bccbar[text=B]{40}{55}
\smallskip
\bccbar[text=C]{0}{31}
%\smallskip
%\bcbar[text=D]{31}
\end{bchart}
\end{document}

我也放弃了一个想法误差线的应用因为我不知道如何用图案填充它们。我的 MWE 是基于对 @esdd 这个问题的重新排列,如何制作具有正最小最大值的条形图

\documentclass{standalone}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
%\input{./plotssettings.tex}
\usepackage{ifthen}
\usetikzlibrary{matrix}
\pgfplotsset{compat=1.15}

\pgfplotstableread[col sep=comma]{
Year,   FarMin, FarMax, NearMin, NearMax, HereMin, HereMax, bMin, bMax 
1930,   20,     50,     10,      30,      15,      40,      20,   50
1940,   10,     60,     15,      60,      20,      70,      10,   60
1950,   15,     78,     nan,     nan,     32,      42,      15,   78
1960,   20,     30,     15,      40,      20,      10,      20,   30
1970,   5,      30,     30,      40,      15,      20,      5,    30
}\datatable


\begin{document}%
\begin{tikzpicture}
\pgfplotsset{
    every axis/.style={
        xbar stacked,
        enlarge y limits=0.15,
        bar width=6pt,
        xmin=0,xmax=80,
    },
    compat/bar nodes=1.8,
    minimum/.style={forget plot,draw=none,fill=none}
}

\pgfplotstablegetcolsof{\datatable}
\pgfmathparse{\pgfplotsretval-1}
\edef\noofcolumns{\pgfmathresult}   % number of columns with numeric data in table
\pgfmathparse{int(\noofcolumns-1)}
\edef\penultimate{\pgfmathresult}

\foreach \datacolno in {1,3,...,\penultimate}{
    \pgfmathparse{int(\datacolno+1)}
    \edef\datanextcolno{\pgfmathresult}
    \pgfmathparse{int((\datanextcolno)/2)}
    \edef\barno{\pgfmathresult}     % number of bar
    \pgfmathparse{8pt*(\barno-(\noofcolumns/2+1)/2)}
    \edef\barshift{\pgfmathresult pt}   % offset within one group of bars (local)
    \pgfmathparse{int((\datacolno-1)/2)}
    \edef\cyclelistshift{\pgfmathresult}    % number of painting
    \ifthenelse{\barno=1}%
        {\def\mystyle{%
            xmajorgrids,
            xlabel=Population,
            %yticklabels from table={\datatable}{Year}
        }}%
        {\def\mystyle{axis lines=none}}
    \begin{axis}[
        bar shift=\barshift,
        cycle list shift=\cyclelistshift,
        \mystyle,
    ]
        \addplot [minimum] table [x index=\datacolno,y=Year] {\datatable};
        \addplot table [x expr=\thisrowno{\datanextcolno}-\thisrowno{\datacolno},y=Year] {\datatable};
        \label{plot:\barno}
    \end{axis}
}

\matrix[
    matrix of nodes,
    draw,
    anchor=north east,
    nodes={inner xsep=.1em},
    column 1/.style={nodes={anchor=center}},
    column 2/.style={nodes={anchor=west}}
] at([shift={(-5pt,-5pt)}]current axis.north east)
{
    \ref{plot:1}&Far\\
    \ref{plot:2}&Near\\
    \ref{plot:3}&Here\\
    \ref{plot:4}&beyond\\
};
\end{tikzpicture}
\end{document}

但在这里我也遇到了问题——读取非数字数据(用字符串替换数字 1930 等之后)、制作图案调色板、条形定位(@Christian Feuersänger 给出的答案这里对我来说并不令人满意,因为刻度标签保持在恒定的间距中)。

一组条形图内有不需要的间隙

答案1

我仍然不能完全确定我是否理解了你的问题,但你会看到下面的示例与你的图片有些相似。如果有什么不合你的口味,请随时询问精确度或发表评论。

\documentclass{standalone}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\usepgfplotslibrary{colorbrewer}
\pgfplotsset{compat=1.16}

\pgfplotsset{
/pgfplots/bar shift auto/.style={
/pgf/bar shift={%
(.5+\plotnumofactualtype)*\pgfplotbarwidth + \plotnumofactualtype*(#1)},
},
}

\pgfplotstableread[col sep=comma]{
Year,   FarMin, FarMax, NearMin, NearMax, HereMin, HereMax, bMin, bMax 
1930,   20,     50,     10,      30,      15,      40,      20,   50
1940,   10,     60,     15,      60,      20,      70,      10,   60
1950,   15,     78,     0,     0,     32,      42,      15,   78
1960,   20,     30,     15,      40,      20,      10,      20,   30
1970,   5,      30,     30,      40,      15,      20,      5,    30
}\datatable

\pgfplotsset{
    every axis/.style={
        xbar stacked,
        bar shift auto=0pt,
        bar width={10/8},
        ymin=1930,ymax=1980,
        ytick={1930,1940,...,1980},
        height=10cm, scale only axis,
        y tick label as interval,
        yticklabel={$\pgfmathprintnumber[1000 sep={}]{\tick}$},
        ymajorgrids
    },
        /pgfplots/bar cycle list/.style={/pgfplots/cycle list={
            {Set1-A,fill=Set1-A!50!white,mark=none},
            {Set1-B,fill=Set1-B!50!white,mark=none},
            {Set1-C,fill=Set1-C!50!white,mark=none},
            {Set1-D,fill=Set1-D!50!white,mark=none},
            {Set1-E,fill=Set1-E!50!white,mark=none},
            {Set1-F,fill=Set1-F!50!white,mark=none},
            {Set1-G,fill=Set1-G!50!white,mark=none},
            {Set1-H,fill=Set1-H!50!white,mark=none},
            },
            },
}

\begin{document}%
\begin{tikzpicture}
   \begin{axis}
    \pgfplotsinvokeforeach{FarMin,FarMax,NearMin,NearMax,HereMin,HereMax,bMin,bMax}{
        \addplot+[] table [y=Year,x=#1] {\datatable};
        \addlegendentry{#1}
        }
    \end{axis}
\end{tikzpicture}
\end{document}

在此处输入图片描述

编辑另一个基于散点图作弊的提议@杰克或者@薛定谔的猫。这可能需要一些清理和简化,但这就是想法。

\documentclass{standalone}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\usepgfplotslibrary{colorbrewer}
\pgfplotsset{compat=1.16}

\pgfplotsset{
/pgfplots/bar shift auto/.style={
/pgf/bar shift={%
(.5+\plotnumofactualtype)*\pgfplotbarwidth + \plotnumofactualtype*(#1)},
},
}

\pgfplotstableread[col sep=comma]{
Year,   FarMin, FarMax, NearMin, NearMax, HereMin, HereMax, bMin, bMax 
1930,   20,     50,     10,      30,      15,      40,      20,   50
1940,   10,     60,     15,      60,      20,      70,      10,   60
1950,   15,     78,     0,       0,       32,      42,      15,   78
1960,   20,     30,     15,      40,      20,      10,      20,   30
1970,   5,      30,     30,      40,      15,      20,      5,    30
}\datatable

\pgfplotsset{
    customaxis1/.style={
        xbar stacked,
        stack negative=separate,
        bar shift auto=0pt,
        bar width={10/8},
        ymin=1930,ymax=1980,
        ytick={1930,1940,...,1980},
        height=10cm, scale only axis,
        y tick label as interval,
        yticklabel={$\pgfmathprintnumber[1000 sep={}]{\tick}$},
        ymajorgrids
    },
        /pgfplots/bar cycle list/.style={/pgfplots/cycle list={
            {Set1-A,fill=Set1-A!50!white,mark=none},
            {Set1-B,fill=Set1-B!50!white,mark=none},
            {Set1-C,fill=Set1-C!50!white,mark=none},
            {Set1-D,fill=Set1-D!50!white,mark=none},
            {Set1-E,fill=Set1-E!50!white,mark=none},
            {Set1-F,fill=Set1-F!50!white,mark=none},
            {Set1-G,fill=Set1-G!50!white,mark=none},
            {Set1-H,fill=Set1-H!50!white,mark=none},
            },
            },
}

\begin{document}%
\begin{tikzpicture}
    \begin{axis}[customaxis1,
            scatter,
            only marks,
            clip mode=individual,
            xmax=150,
            %colormap/Set1,
            cycle list/Set1-4,
        ]
        \addplot[Set1-A,
            visualization depends on={\thisrow{FarMin} \as \startvalue},
            visualization depends on={\thisrow{FarMax} \as \endvalue},
            scatter/@pre marker code/.append code={\fill [draw=black,fill=Set1-A] (axis direction cs:0,0) rectangle (axis direction cs:\endvalue,2.5);
                    \pgfplotsset{mark=none}}
        ] table [y expr={\thisrow{Year}+0*2.5},x=FarMin] {\datatable};
        \addplot[Set1-B,
            visualization depends on={\thisrow{NearMin} \as \startvalue},
            visualization depends on={\thisrow{NearMax} \as \endvalue},
            scatter/@pre marker code/.append code={\fill [draw=black,fill=Set1-B] (axis direction cs:0,0) rectangle (axis direction cs:\endvalue,2.5);
                    \pgfplotsset{mark=none}}
        ] table [y expr={\thisrow{Year}+1*2.5},x=NearMin] {\datatable};
        \addplot[Set1-C,
            visualization depends on={\thisrow{HereMin} \as \startvalue},
            visualization depends on={\thisrow{HereMax} \as \endvalue},
            scatter/@pre marker code/.append code={\fill [draw=black,fill=Set1-C] (axis direction cs:0,0) rectangle (axis direction cs:\endvalue,2.5);
                    \pgfplotsset{mark=none}}
        ] table [y expr={\thisrow{Year}+2*2.5},x=HereMin] {\datatable};
        \addplot[Set1-D,
            visualization depends on={\thisrow{bMin} \as \startvalue},
            visualization depends on={\thisrow{bMax} \as \endvalue},
            scatter/@pre marker code/.append code={\fill [draw=black,fill=Set1-D] (axis direction cs:0,0) rectangle (axis direction cs:\endvalue,2.5);
                    \pgfplotsset{mark=none}}
        ] table [y expr={\thisrow{Year}+3*2.5},x=bMin] {\datatable};
    \end{axis}
\end{tikzpicture}

\end{document}

在此处输入图片描述

相关内容