我正在尝试从数据文件中创建类似于图片中所示的缺口箱线图。
我已经管理了可以按照我想要的方式创建带有缺口的箱线图的代码(下面的代码没有轴和addplot
命令),但在添加轴时遇到了问题。当我使用时,绘制箱线图的设置不起作用\addplot
,如果我不使用,\addplot
我会收到其他错误,或者根据我如何移动轴的代码,我只会得到轴。我想不出如何解决这个问题。
\documentclass{article}
\usepackage{pgfplots}
\usepackage{filecontents}
\usepackage{pgfplotstable}
\usetikzlibrary{calc}
\begin{document}
\begin{filecontents}{boxplot.dat}
1 1 1.2 0.4 1.5 0.2 1.05 0.95
2 2 2.3 1.5 2.7 1 2.05 1.95
3 0.7 1.4 0.5 1.9 0.1 0.75 0.65
4 0.7 1.4 0.5 1.9 0.1 0.75 0.65
\end{filecontents}
\pgfplotstableread{boxplot.dat}{\infotable}
\pgfplotstablegetrowsof{boxplot.dat}
\pgfmathsetmacro{\rows}{\pgfplotsretval-1}
\begin{tikzpicture}
\begin{axis}[
xticklabels={1, 2, 3, 4},
]
\addplot{
\foreach \i in {0,...,\rows}{%
%x-values
\pgfplotstablegetelem{\i}{[index] 0}\of{\infotable}
%Middle
\let\xM\pgfplotsretval
%Left
\pgfmathsetmacro{\xL}{\xM-0.25}
\pgfmathsetmacro{\xLInd}{\xM-0.125}
%Right
\pgfmathsetmacro{\xR}{\xM+0.25}
\pgfmathsetmacro{\xRInd}{\xM+0.125}
%y-values
\pgfplotstablegetelem{\i}{[index] 4}\of{\infotable}
\let\yTopWhisk\pgfplotsretval
\pgfplotstablegetelem{\i}{[index] 2}\of{\infotable}
\let\yBoxTop\pgfplotsretval
\pgfplotstablegetelem{\i}{[index] 6}\of{\infotable}
\let\yTopInd\pgfplotsretval
\pgfplotstablegetelem{\i}{[index] 1}\of{\infotable}
\let\yMedian\pgfplotsretval
\pgfplotstablegetelem{\i}{[index] 7}\of{\infotable}
\let\yBottomInd\pgfplotsretval
\pgfplotstablegetelem{\i}{[index] 3}\of{\infotable}
\let\yBoxBottom\pgfplotsretval
\pgfplotstablegetelem{\i}{[index] 5}\of{\infotable}
\let\yBottomWhisk\pgfplotsretval
%top part
\draw [blue] (\xLInd,\yMedian) -- (\xL,\yTopInd) -- (\xL,\yBoxTop) -- (\xR,\yBoxTop) -- (\xR,\yTopInd) -- (\xRInd,\yMedian);
%bottom part
\draw [blue] (\xLInd,\yMedian) -- (\xL,\yBottomInd) -- (\xL,\yBoxBottom) -- (\xR,\yBoxBottom) -- (\xR,\yBottomInd) -- (\xRInd,\yMedian);
%median
\draw [red] (\xLInd,\yMedian) -- (\xRInd,\yMedian);
%top whisker
\draw [black] (\xM,\yBoxTop) -- (\xM,\yTopWhisk);
\draw [black] (\xL,\yTopWhisk) -- (\xR,\yTopWhisk);
%bottom whisker
\draw [black] (\xM,\yBoxBottom) -- (\xM,\yBottomWhisk);
\draw [black] (\xL,\yBottomWhisk) -- (\xR,\yBottomWhisk);
}%
}
\end{axis}
\end{tikzpicture}
\end{document}
答案1
自 1.8 版以来,PGFPlots 可以绘制箱线图(请原谅这个双关语)。您可以相对轻松地添加绘制缺口的功能,也可以使用来自从表中读取箱线图准备好的值从表中提供值。
上面的图像是使用
\pgfplotstableread{
lw lq med uq uw ln un
5 7 8.5 9.5 10 8.0 9.0
4 5 6.5 8.5 9.5 5.5 7.2
}\datatable
\begin{tikzpicture}
\begin{axis}[
boxplot/draw direction=y,
x=2cm,
boxplot/box extend=0.3,
boxplot/notch width=0.5
]
\addplot +[
boxplot prepared from table={
table=\datatable,
lower whisker=lw,
upper whisker=uw,
lower quartile=lq,
upper quartile=uq,
lower notch=ln,
upper notch=un,
median=med
}, boxplot prepared
] coordinates {(1,4)};
\addplot +[
boxplot prepared from table={
table=\datatable,
row=1,
lower whisker=lw,
upper whisker=uw,
lower quartile=lq,
upper quartile=uq,
lower notch=ln,
upper notch=un,
median=med
}, boxplot prepared
] coordinates {(2,11) (2,11.5)};
\end{axis}
\end{tikzpicture}
完整代码如下:
\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.8}
\usepgfplotslibrary{statistics}
\begin{document}
\makeatletter
\pgfplotsset{
boxplot/lower notch/.initial=\pgfutil@empty,
boxplot/upper notch/.initial=\pgfutil@empty,
boxplot/notch width/.initial=0.9,
boxplot/draw/box/.code={%
\draw[/pgfplots/boxplot/every box/.try]
(boxplot box cs:\pgfplotsboxplotvalue{lower quartile},0)
-- (boxplot box cs:\pgfplotsboxplotvalue{lower notch},0)
-- (boxplot box cs:\pgfplotsboxplotvalue{median},0.5-\pgfplotsboxplotvalue{notch width}/2)
-- (boxplot box cs:\pgfplotsboxplotvalue{upper notch},0)
-- (boxplot box cs:\pgfplotsboxplotvalue{upper quartile},0)
-- (boxplot box cs:\pgfplotsboxplotvalue{upper quartile},1)
-- (boxplot box cs:\pgfplotsboxplotvalue{upper notch},1)
-- (boxplot box cs:\pgfplotsboxplotvalue{median},0.5+\pgfplotsboxplotvalue{notch width}/2)
-- (boxplot box cs:\pgfplotsboxplotvalue{lower notch},1)
-- (boxplot box cs:\pgfplotsboxplotvalue{lower quartile},1)
-- cycle
;
},%
boxplot/draw/median/.code={%
\draw[/pgfplots/boxplot/every median/.try]
(boxplot box cs:\pgfplotsboxplotvalue{median},0.5-\pgfplotsboxplotvalue{notch width}/2)
--
(boxplot box cs:\pgfplotsboxplotvalue{median},0.5+\pgfplotsboxplotvalue{notch width}/2)
;
},%
boxplot prepared from table/.code={
\def\tikz@plot@handler{\pgfplotsplothandlerboxplotprepared}%
\pgfplotsset{
/pgfplots/boxplot prepared from table/.cd,
#1,
}
},
/pgfplots/boxplot prepared from table/.cd,
table/.code={\pgfplotstablecopy{#1}\to\boxplot@datatable},
row/.initial=0,
make style readable from table/.style={
#1/.code={
\pgfplotstablegetelem{\pgfkeysvalueof{/pgfplots/boxplot prepared from table/row}}{##1}\of\boxplot@datatable
\pgfplotsset{boxplot/#1/.expand once={\pgfplotsretval}}
}
},
make style readable from table=lower whisker,
make style readable from table=upper whisker,
make style readable from table=lower quartile,
make style readable from table=upper quartile,
make style readable from table=median,
make style readable from table=lower notch,
make style readable from table=upper notch
}
\pgfplotstableread{
lw lq med uq uw ln un
5 7 8.5 9.5 10 8.0 9.0
4 5 6.5 8.5 9.5 5.5 7.2
}\datatable
\begin{tikzpicture}
\begin{axis}[
boxplot/draw direction=y,
x=2cm,
boxplot/box extend=0.3,
boxplot/notch width=0.5
]
\addplot +[
boxplot prepared from table={
table=\datatable,
lower whisker=lw,
upper whisker=uw,
lower quartile=lq,
upper quartile=uq,
lower notch=ln,
upper notch=un,
median=med
}, boxplot prepared
] coordinates {(1,4)};
\addplot +[
boxplot prepared from table={
table=\datatable,
row=1,
lower whisker=lw,
upper whisker=uw,
lower quartile=lq,
upper quartile=uq,
lower notch=ln,
upper notch=un,
median=med
}, boxplot prepared
] coordinates {(2,11) (2,11.5)};
\end{axis}
\end{tikzpicture}
\end{document}