当 pgfplots 中未使用(无值)时隐藏特定 ybar

当 pgfplots 中未使用(无值)时隐藏特定 ybar

我正在尝试绘制调查结果。但是,我想根据结果打开或关闭一个栏(无答案)。也就是说,如果没有空答案,则无需显示它。

但是,我如何才能隐藏图中的其中一个条形图(给定条件)。此外,我正在使用该statistics库自动计算直方图。有没有办法动态更改箱体?或者使用后端更容易pgfplots

\documentclass{article}

\usepackage{filecontents}

\begin{filecontents}{data.csv}
a;b;c
4;3;3
1;3;1
1;4;4
1;3;4
2;4;4
2;4;4
4;3;-1
4;4;4
3;3;3
2;4;3
3;3;3
3;2;2
4;4;3
\end{filecontents}

\usepackage{pgfplots, pgfplotstable}
\usepgfplotslibrary{statistics}

\pgfplotstableread[col sep = semicolon]{data.csv}\mydata

\makeatletter
\newcommand*\NNC{\pgfmathprintnumber{\pgfkeysvalueof{/data point/y}}}
\newcommand*\enlargexlimits{.1} % default value for enlarge x limits 
\pgfplotsset{
  width=\linewidth,
  height=0.5\linewidth,
  grid style={dashed}, % make the grid dashe
  % Bottom nodes 
  calculate full offset/.code={
      \pgfkeys{/pgf/fpu=true,/pgf/fpu/output format=fixed}
      \pgfmathsetmacro\testmacro{((\pgfplotspointmeta-\pgfkeysvalueof{/pgfplots/ymin})*10^\pgfplots@data@scale@trafo@EXPONENT@y)*\pgfplots@y@veclength}
      \pgfkeys{/pgf/fpu=false}
  },%
  nodes near coords bottom/.style={
    every node near coord/.append style={
      white,
      /pgfplots/calculate full offset,
      yshift=-\testmacro,
      xshift={
        (\pgfkeysvalueof{/pgfplots/width}-45pt) % every plot is 45pt smaller then the width
        /(1+2*\enlargexlimits) % correction for enlarge x limits
        /\pgfkeysvalueof{/pgfplots/hist/bins} % number of bins
        /2% shift only half of bin width
      }
    },
    nodes near coords={% 
      \pgfmathparse{
        \pgfkeysvalueof{/data point/x}<0.9*\pgfkeysvalueof{/pgfplots/hist/data max}?%
          "\noexpand\NNC"%  if true print nodes near coords
          :% if false suppress the additional node near coords
      }\pgfmathresult%
    },
  },%
  % Minimal bar grid, sets the grid on top and white
  minimal bar grid/.style={
    axis on top,
    ymajorgrids, tick align=inside,
    major grid style={draw=white},
    tickwidth=0pt,
    grid style={solid},
    axis x line*=bottom,
    y axis line style={opacity=0},
    legend style={
      font=\footnotesize,
      draw=none %eliminate the border
    },
  },
  minimal ybar interval/.style={
    ybar interval,
    bar interval width=.8pt,
    minimal bar grid,
    nodes near coords={\pgfmathprintnumber[fixed zerofill,precision=0]{\pgfplotspointmeta}},
    nodes near coords bottom,
  },
  bar color/.style={
    gray,
    fill=gray,
  }
}
\makeatother

\newcommand{\myplot}[1]{%
\begin{tikzpicture}
  \begin{axis}[
    minimal ybar interval,
    ymin=0,
    enlarge x limits=0,
    xticklabels={No Ans.,A,B,C,D},
    x tick label style={font=\footnotesize}
  ]
  \addplot +[
    bar color,
    hist={bins=5,data min=0,data max=5}
  ] table [y=#1] {\mydata};
  \end{axis}
\end{tikzpicture}
}

\pagestyle{empty}
\begin{document}

\myplot{a}

\myplot{b}

\myplot{c}

\end{document}

例如,对于前两个图,我希望只显示从 A 到 D 的条形图,但在最后一个图中(其中有一些未回答的问题),我希望显示无答案的数量。

在此处输入图片描述

答案1

继续@percuesse 的评论:

在之后添加以下几行\makeatletter

\makeatletter
\def\pgfplotsplothandlerhistadvancebin#1{
    \pgfplotsarrayselect{#1}\of{pgfp@hist}\to\pgfplots@loc@TMPa%
    \pgfplotsutil@advancestringcounter\pgfplots@loc@TMPa
    \pgfplotsarrayletentry{#1}\of{pgfp@hist}=\pgfplots@loc@TMPa
    % ↑↑↑↑↑↑↑  old  definition  ↑↑↑↑↑↑↑
    % ↓↓↓↓↓↓↓ I added this line ↓↓↓↓↓↓↓
    \message{pglplots express: bin number #1 is now counting to \pgfplots@loc@TMPa.^^J}
}

现在您可以看到 pgfplots 如何计算您的数据。(参见附录 A)应该相对容易一些

  • \pgfplotsplothandlerhistadvancebin例如添加​​ 更多 的 东西\expandafter\gdef\csname pgfplotstellmeifbin#1isnonempty\endcsname{YES}.
  • 传递你的数据\addplot
  • 放弃该情节。(但\gdef保留定义的宏。)
  • 开始一个新的情节,这一次你知道哪个条是非空的。

进而?

让我们从新文档开始。请注意,我修复了hist/symbolic coords/.stylefrom的定义pgfplotsplothandlers.code.tex

\documentclass[border=9,tikz]{standalone}
\usepackage{pgfplots}
\usepgfplotslibrary{statistics}
\makeatletter
\def\pgfplotsplothandlerhistadvancebin#1{
    \pgfplotsarrayselect{#1}\of{pgfp@hist}\to\pgfplots@loc@TMPa
    \pgfplotsutil@advancestringcounter\pgfplots@loc@TMPa
    \pgfplotsarrayletentry{#1}\of{pgfp@hist}=\pgfplots@loc@TMPa
    % ↑↑↑↑↑↑↑  old  definition  ↑↑↑↑↑↑↑
    % ↓↓↓↓↓↓↓ I added this line ↓↓↓↓↓↓↓
    \expandafter\gdef\csname bin#1isnonempty\endcsname{YES}
}
\pgfplotsset{
    hist/symbolic coords/.style={
        /pgfplots/symbolic coords={hist/data}{#1},
        /pgfplots/symbolic coords={x}{#1},
    }
}
\pgfplotstableread[row sep=\\]{
    datb\\
    A\\A\\A\\A\\
    B\\B\\
    C\\C\\C\\C\\C\\
    D\\D\\D\\
}\mydatb
\pgfplotstableread[row sep=\\]{
    datb\\
    C\\C\\C\\C\\C\\
    D\\D\\D\\
}\mydatc
\pgfplotstableread[row sep=\\]{
    datc\\
    A\\A\\A\\A\\
    B\\B\\
    D\\D\\D\\
}\mydatd
\pgfplotstableread[row sep=\\]{
    datb\\
    A\\A\\A\\A\\
    B\\B\\
    C\\C\\C\\C\\C\\
}\mydate
\begin{document}

因此我们有四个图:

\def\myplot#1{
    \begin{tikzpicture}
        \begin{axis}[ybar interval,ymin=0,xmin=A,xmax=PhantomMax,
                hist={bins=4,symbolic coords={A,B,C,D,PhantomMax}}]
        \addplot table[y index=0]{#1};
        \end{axis}
    \end{tikzpicture}
}
\myplot\mydatb
\myplot\mydatc
\myplot\mydatd
\myplot\mydate

然后我们可以报告结果:

\def\YES{YES}
\newcount\countofnonzero
\def\myplot#1{
    \countofnonzero=0
    \foreach\i in{0,...,3}{\expandafter\gdef\csname bin\i isnonempty\endcsname{NO}}
    \begin{tikzpicture}
        \begin{axis}[ybar interval,ymin=0,xmin=A,xmax=PhantomMax,
                hist={bins=4,symbolic coords={A,B,C,D,PhantomMax}}]
        \addplot table[y index=0]{#1};
        \end{axis}
        \node at(current bounding box.south)[yshift=-10]{
            \foreach\i in{0,...,3}{
                \expandafter\let\expandafter\YESorNO\csname bin\i isnonempty\endcsname
                \YESorNO
                \ifx\YESorNO
                    \YES\global\advance\countofnonzero1
                \fi
            }
            total=\the\countofnonzero
        };
    \end{tikzpicture}
}
\myplot\mydatb
\myplot\mydatc
\myplot\mydatd
\myplot\mydate

最后我们可以正确地绘制它们:

\def\myplot#1{
    \countofnonzero=0
    \gdef\listognonzero{}
    \foreach\i in{0,...,3}{
        \expandafter\gdef\csname bin\i isnonempty\endcsname{NO}}
    \begin{tikzpicture}
        \begin{axis}[ybar interval,ymin=0,xmin=A,xmax=PhantomMax,
                hist={bins=4,symbolic coords={A,B,C,D,PhantomMax}}]
        \addplot table[y index=0]{#1};
        \end{axis}
    \end{tikzpicture}
    \foreach\i/\a in{0/A,1/B,2/C,3/D}{
        \expandafter\let\expandafter\YESorNO\csname bin\i isnonempty\endcsname
        \ifx\YESorNO\YES
            \global\advance\countofnonzero1
            \xdef\listognonzero{\listognonzero\a,}
        \fi
    }
    \xdef\listognonzero{\listognonzero PhantomMax}
    \edef\numberofnonzero{\the\countofnonzero}
    \begin{tikzpicture}
        \begin{axis}[ybar interval,ymin=0,xmax=PhantomMax,
                hist={bins=\numberofnonzero,symbolic coords/.expanded=\listognonzero}]
        \addplot[fill=red]table[y index=0]{#1};
        \end{axis}
    \end{tikzpicture}
}

\myplot\mydatb
\myplot\mydatc
\myplot\mydatd
\myplot\mydate

附录 A

pglplots express: bin number 4 is now counting to 1.
pglplots express: bin number 1 is now counting to 1.
pglplots express: bin number 1 is now counting to 2.
pglplots express: bin number 1 is now counting to 3.
pglplots express: bin number 2 is now counting to 1.
pglplots express: bin number 2 is now counting to 2.
pglplots express: bin number 4 is now counting to 2.
pglplots express: bin number 4 is now counting to 3.
pglplots express: bin number 3 is now counting to 1.
pglplots express: bin number 2 is now counting to 3.
pglplots express: bin number 3 is now counting to 2.
pglplots express: bin number 3 is now counting to 3.
pglplots express: bin number 4 is now counting to 4.
LaTeX Font Info:    External font `cmex10' loaded for size
(Font)              <7> on input line 117.
LaTeX Font Info:    External font `cmex10' loaded for size
(Font)              <5> on input line 117.

Overfull \hbox (10.19409pt too wide) in paragraph at lines 117--118
[][]
 []


Underfull \hbox (badness 10000) in paragraph at lines 117--118

 []

pglplots express: bin number 3 is now counting to 1.
pglplots express: bin number 3 is now counting to 2.
pglplots express: bin number 4 is now counting to 1.
pglplots express: bin number 3 is now counting to 3.
pglplots express: bin number 4 is now counting to 2.
pglplots express: bin number 4 is now counting to 3.
pglplots express: bin number 3 is now counting to 4.
pglplots express: bin number 4 is now counting to 4.
pglplots express: bin number 3 is now counting to 5.
pglplots express: bin number 4 is now counting to 5.
pglplots express: bin number 3 is now counting to 6.
pglplots express: bin number 2 is now counting to 1.
pglplots express: bin number 4 is now counting to 6.

Overfull \hbox (10.19409pt too wide) in paragraph at lines 119--120
[][]
 []


Underfull \hbox (badness 10000) in paragraph at lines 119--120

 []

pglplots express: bin number 3 is now counting to 1.
pglplots express: bin number 1 is now counting to 1.
pglplots express: bin number 4 is now counting to 1.
pglplots express: bin number 4 is now counting to 2.
pglplots express: bin number 4 is now counting to 3.
pglplots express: bin number 4 is now counting to 4.
pglplots express: bin number 0 is now counting to 1.
pglplots express: bin number 4 is now counting to 5.
pglplots express: bin number 3 is now counting to 2.
pglplots express: bin number 3 is now counting to 3.
pglplots express: bin number 3 is now counting to 4.
pglplots express: bin number 2 is now counting to 1.
pglplots express: bin number 3 is now counting to 5.

Overfull \hbox (10.19409pt too wide) in paragraph at lines 121--122
[][]
 []


Underfull \hbox (badness 10000) in paragraph at lines 121--122

 []

答案2

您可以根据要显示的列对表格进行排序。然后,您可以计算唯一项目并将索引与相应的标签进行匹配。这当然是一种相当复杂的做事方式,我认为可以作为功能请求向 Christian Feuersänger 提出。但是,我注意到无论如何,bin 计算都存在一些敏感性。只需编写bins=3您自己的代码,第二个代码就会报告0,7,6元素计数可能是相对幅度和舍入问题。这也可以是一个错误报告。

我已删除大多数轴选项以减少混乱。

\documentclass{article}
\usepackage{pgfplotstable,xstring}
\pgfplotsset{compat=1.12}
\usepgfplotslibrary{statistics}

\newcount\mybincount
\pgfplotstableread[col sep = semicolon]{
a;b;c
4;3;3
1;3;1
1;4;4
1;3;4
2;4;4
2;4;4
4;3;-1
4;4;4
3;3;3
2;4;3
3;3;3
3;2;2
4;4;3
}\mydata

\newcommand{\myplot}[1]{%
\mybincount=0\def\myuniqueindex{}
\pgfplotstablesort[sort key=#1]\mysorteddata\mydata
\pgfplotstableforeachcolumnelement{#1}\of\mysorteddata\as\cell{%
\ifx\cell\prevvalue%IF they are the same ignore
\else% Otherwise 
\xdef\prevvalue{\cell}% Make this the new previous value
\global\advance\mybincount by1% add to the unique items count and index
\expandafter\xdef\expandafter\myuniqueindex{\myuniqueindex,\cell}%
\fi%
\foreach\x/\y in{-1/{No Ans.},1/A,2/B,3/C,4/D}{% Replace strings with indices
\IfSubStr{\myuniqueindex}{\x}{%
\StrSubstitute{\myuniqueindex}{\x}{\y}[\myuniqueindex]%Then remove the preceeding comma
\IfBeginWith{\myuniqueindex}{,}{\StrGobbleLeft\myuniqueindex{1}[\myuniqueindex]}{}%
\global\let\myuniqueindex\myuniqueindex%
}{}}%
}\show\myuniqueindex\showthe\mybincount%
\begin{tikzpicture}
  \begin{axis}[width=.4\textwidth,
    ybar interval,
    bar interval width=.8pt,
    ymin=0,ytick={1,...,6},
    enlarge x limits=0,
    xticklabels/.expand once=\myuniqueindex,
    x tick label style={scale=0.5}
  ]
  \addplot +[fill=gray,hist={bins=\the\mybincount,data min=0,data max=5}] table [y=#1] {\mydata};
  \end{axis}
\end{tikzpicture}}
\begin{document}

\myplot{a}\myplot{b}\myplot{c}

\end{document}

在此处输入图片描述

相关内容