如何更改 pgfplots 箱线图中的标记

如何更改 pgfplots 箱线图中的标记

我有自己非常喜欢的箱线图自定义样式。我非常喜欢它,我想在任何地方使用它。我把它和旧箱线图,它满足了我想要的一切。

但是,新样式的箱线图破坏了这种风格。具体来说,我喜欢使用mark=x离群值,但新代码会忽略它。

探索(定义箱线图代码的库)的代码pgfplots.statistics,我意识到有一个\pgfplots@boxplot@ensure@plot@mark宏,1)检查的值\ifpgfplots@boxplot@ensure@plot@mark并(如果为真?)重置标记(即mark=*)。

稍后,它if被分配给一个名为的处理程序boxplots/ensure mark,并带有一个相当神秘的注释:

% mainly used for compatibility.
boxplot/ensure mark/.is if=pgfplots@boxplot@ensure@plot@mark,

现在,我和其他人一样喜欢兼容性,但我更喜欢我的箱线图风格,而且我喜欢生活在边缘,所以我正在寻找方法来扭转这种局面,并不管后果。(顺便说一句,如果有人能向我解释这些后果可能是什么,我将不胜感激)。

我试过

\makeatletter
\pgfplots@boxplot@ensure@plot@markfalse
\makeatother

在我的序言中,但没有成功。

我试过了

\pgfplotsset{
  boxplot/ensure mark=false,
}

但这也没什么作用。

我唯一能强迫自己留下印记的方法就是重复这mark=x句话箱线图已被调用。这确实工作,但我想知道是否有更好的解决方案。特别是考虑到似乎有一个针对此任务的切换开关。

这是MWE:

\documentclass{article}
\usepackage{pgfplots}
\usetikzlibrary[pgfplots.statistics,calc]

% Tried this, didn't work
% \makeatletter
% \pgfplots@boxplot@ensure@plot@markfalse
% \makeatother

\pgfplotsset{
  compat=1.12,
  boxplot/box width/.initial=1em,
  solid boxes/.style={
    clip = false,
    solid,
    mark=x,
    boxplot/draw direction=y,
    boxplot/whisker extend=0,
    boxplot/draw/median/.code={%
      \draw[mark size=2pt,/pgfplots/boxplot/every median/.try]
        \pgfextra
        \pgftransformshift{
          \pgfplotsboxplotpointabbox
            {\pgfplotsboxplotvalue{median}}
            {0.5}
        }
        \pgfsetfillcolor{white}
        \pgfuseplotmark{*}
        \endpgfextra
      ;
    },
    boxplot/draw/box/.code={
      \draw[fill,/pgfplots/boxplot/every box/.try]
        ($(boxplot box cs:\pgfplotsboxplotvalue{lower quartile},0.5)!0.5\pgfkeysvalueof{/pgfplots/boxplot/box width}!(boxplot box cs:\pgfplotsboxplotvalue{lower quartile},0)$)
        rectangle
        ($(boxplot box cs:\pgfplotsboxplotvalue{upper quartile},0.5)!0.5\pgfkeysvalueof{/pgfplots/boxplot/box width}!(boxplot box cs:\pgfplotsboxplotvalue{upper quartile},1)$)
      ;
    }
  },
  % Tried this, didn't work
  boxplot/ensure mark/.is if=pgfplots@boxplot@ensure@plot@mark,
  boxplot/ensure mark=false,
}

\begin{document}

\begin{figure}
  \centering
  \begin{tikzpicture}
    \begin{axis}[
        xtick={1,2,3},
        xticklabels={Group A, Group B, Group C},
        % This applies the style, but the mark gets overwritten
        solid boxes,
      ]
      \addplot+[% Group A:
        boxplot prepared={
          lower whisker=42, lower quartile=45,
          median=47,
          upper quartile=47.5, upper whisker=48,
        },
      ] table[row sep=\\,y index=0] { 40\\ 34\\ 56\\ };
      \addplot+[% Group B:
        boxplot prepared={
          lower whisker=36, lower quartile=39,
          median=40,
          upper quartile=41, upper whisker=43,
        },
      ] coordinates {};
      \addplot+[% Group C:
        boxplot prepared={
          lower whisker=41, lower quartile=44,
          median=45,
          upper quartile=46, upper whisker=47,
        },
        % This works, but is not a complete solution
        mark=x,
      ] coordinates {(0,35) (0,55)};
    \end{axis}
  \end{tikzpicture}
  \caption[A caption]{A caption for my figure}
\end{figure}

\end{document}

并附有一张图片和有用的注释:

MWE 的输出:一个带有三个箱子的垂直箱线图。左侧的箱子用圆圈标记离群值;右侧的箱子用 exes 标记离群值。后者标有一张笑脸。

答案1

尽管这个问题很老了,但我找不到另一个能解决这个问题的方法。我稍微修改了一下代码,设法让它工作了。具体来说,我使用了命令

every boxplot/.style={mark=x,every mark/.append style={mark size=1.5pt}}

并且成功了 ;)

答案2

我不知道为什么这有效,但以下步骤解决了我遇到的问题。为了做到这一点,我必须:

1)指定一个循环列表(不必指定任何类型的标记:下面的示例使用color list,据我所知,它只会改变颜色);和

2)对我使用的样式进行一些更改,以便将其插入every axis plot

两者结合起来,可生成所需的输出,如下所示。更正后的 MWE 位于底部。

在此处输入图片描述

理解这一点很好为什么这是有效的,以及你可以如何使用它们\pgfplots@boxplot@ensure@plot@markboxplot/ensure mark做我想象中的用途。但由于这些步骤成功地做到了我想要的,所以我将它们留在这里作为答案。

\documentclass{article}
\usepackage{pgfplots}
\usetikzlibrary[pgfplots.statistics,calc]

\pgfplotsset{
  compat=1.12,
  boxplot/box width/.initial=1em,
  solid boxes/.style={
    clip = false,
    every axis plot/.style={
      solid,
      mark=x,
      boxplot/draw direction=y,
      boxplot/whisker extend=0,
      boxplot/draw/median/.code={%
        \draw[mark size=2pt,/pgfplots/boxplot/every median/.try]
          \pgfextra
          \pgftransformshift{
            \pgfplotsboxplotpointabbox
              {\pgfplotsboxplotvalue{median}}
              {0.5}
          }
          \pgfsetfillcolor{white}
          \pgfuseplotmark{*}
          \endpgfextra
        ;
      },
      boxplot/draw/box/.code={
        \draw[fill,/pgfplots/boxplot/every box/.try]
          ($(boxplot box cs:\pgfplotsboxplotvalue{lower quartile},0.5)!0.5\pgfkeysvalueof{/pgfplots/boxplot/box width}!(boxplot box cs:\pgfplotsboxplotvalue{lower quartile},0)$)
          rectangle
          ($(boxplot box cs:\pgfplotsboxplotvalue{upper quartile},0.5)!0.5\pgfkeysvalueof{/pgfplots/boxplot/box width}!(boxplot box cs:\pgfplotsboxplotvalue{upper quartile},1)$)
        ;
      }
    }
  },
}

\begin{document}

\begin{figure}
  \centering
  \begin{tikzpicture}
    \begin{axis}[
        xtick={1,2,3},
        xticklabels={Group A, Group B, Group C},
        % This somehow fixes everything
        cycle list name={color list},
        solid boxes,
      ]
      \addplot+[% Group A:
        boxplot prepared={
          lower whisker=42, lower quartile=45,
          median=47,
          upper quartile=47.5, upper whisker=48,
        },
      ] table[row sep=\\,y index=0] { 40\\ 34\\ 56\\ };
      \addplot+[% Group B:
        boxplot prepared={
          lower whisker=36, lower quartile=39,
          median=40,
          upper quartile=41, upper whisker=43,
        },
      ] coordinates {};
      \addplot+[% Group C:
        boxplot prepared={
          lower whisker=41, lower quartile=44,
          median=45,
          upper quartile=46, upper whisker=47,
        },
      ] coordinates {(0,35) (0,55)};
    \end{axis}
  \end{tikzpicture}
  \caption[A caption]{A caption for my figure}
\end{figure}

\end{document}

相关内容