答案1
有一个相当新的 CTAN 包叫做tikzviolinplots无缝地填补了这一空白(至少对我来说是这样)。它遵循此包的 MWE(最小工作示例):
\documentclass{article}
\usepackage{pgfplots}
\usepackage{tikzviolinplots}
\usepgfplotslibrary{external}
\tikzexternalize
\usepackage{minted}
\usemintedstyle{gruvbox-light}
\usepackage{scontents}
\begin{scontents}[write-out=violinandboxplotexample.dat]
A B C D
0.876 0.574 2.175 1.684
1.015 0.822 2.121 2.290
0.995 1.266 1.916 2.184
1.101 0.740 2.044 2.065
1.222 0.636 2.004 2.248
0.712 1.753 2.038 2.200
1.063 0.873 1.974 1.865
0.973 1.020 2.145 1.895
1.174 0.763 2.052 2.240
1.057 1.293 2.079 2.360
1.004 0.853 2.064 1.695
0.909 0.694 2.136 1.837
1.108 0.849 2.000 1.744
1.210 0.468 2.010 1.820
0.958 0.767 1.824 2.158
1.119 0.940 2.034 1.846
1.000 0.962 1.967 2.545
0.954 1.551 1.833 1.816
0.918 0.755 1.914 2.369
1.093 0.973 1.997 1.543
\end{scontents}
\begin{document}
\begin{tikzpicture}
\violinsetoptions[
averages,
data points,
scaled,
]{
xmin=0,xmax=5,
ymin=0,ymax=3,
xlabel style={
yshift = {-2*height("a")}
},
ymajorgrids=true,
ylabel={Same property},
}
\violinplotwholefile[%
primary color=red,
secondary color=blue,
indexes={A,B,C,D},
spacing=1.0,
labels={%
$\alpha$,
$\beta$,
$\gamma$,
$\delta$,
},
col sep=tab,
dataset size=1pt,
dataset mark=*,
dataset fill=black!50!white,
dataset fill opacity=1.0,
average mark=x,
average size=5pt,
]{violinandboxplotexample.dat}
\end{tikzpicture}
\end{document}
最后有一个 CTAN 包可以解决这个问题!:) 感谢 Pedro Callil-Soares...
编辑:您必须使用该-shell-escape
选项才能使其工作。
答案2
Gnuplot 可以做到这一点 - 参见
https://gnuplot.sourceforge.net/demo/violinplot.html。通过一些技巧,可以让 PGFPlots 在 的帮助下做到这一点raw gnuplot
。无法使用链接中的表格来实现这一点,因为 PGFPlots 坚持从第一个图中创建点。-因此代码保存了三个附加文件“kdensity1.dat”、“kdensity2.dat”和“kdensity3.dat”
要运行代码,您需要安装 Gnuplot 并且需要--shell-escape
。
\begin{filecontents*}{data1.dat}
5 1
6 1
3 1
3 1
7 1
8 1
3 1
8 1
7 1
9 1
5 1
\end{filecontents*}
\begin{filecontents*}{data2.dat}
12 2
14 2
12 2
8 2
22 2
22 2
12 2
12 2
7 2
12 2
2 2
\end{filecontents*}
\begin{filecontents*}{data3.dat}
20 3
20 3
21 3
20 3
22 3
21 3
20 3
24 3
22 3
21 3
20 3
\end{filecontents*}
\documentclass[tikz, border=1 cm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\usepgfplotslibrary{fillbetween}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
xmin=0, xmax=25,
ymin=0, ymax=4,
ytick={1,2,3},
yticklabels={Condition 1, Condition 2, Condition 3},
]
\addplot[draw=none] gnuplot[raw gnuplot] {
plot 0; %included to avoid warning of empty plot
set table "kdensity1.dat";
plot "data1.dat" using 1:2 smooth kdensity bandwidth 1.;
unset table;
set table "kdensity2.dat";
plot "data2.dat" using 1:2 smooth kdensity bandwidth 1.;
unset table;
set table "kdensity3.dat";
plot "data3.dat" using 1:2 smooth kdensity bandwidth 1.;
unset table;
};
\addplot[draw=none, name path=p1, y filter/.expression={1+0.1*y}] table {kdensity1.dat};
\addplot[draw=none, name path=m1, y filter/.expression={1-0.1*y}] table {kdensity1.dat};
\addplot[red!50] fill between [of=p1 and m1];
\addplot[draw=none, name path=p2, y filter/.expression={2+0.1*y}] table {kdensity2.dat};
\addplot[draw=none, name path=m2, y filter/.expression={2-0.1*y}] table {kdensity2.dat};
\addplot[green!50] fill between [of=p2 and m2];
\addplot[draw=none, name path=p3, y filter/.expression={3+0.1*y}] table {kdensity3.dat};
\addplot[draw=none, name path=m3, y filter/.expression={3-0.1*y}] table {kdensity3.dat};
\addplot[blue!50] fill between [of=p3 and m3];
\end{axis}
\end{tikzpicture}
\end{document}
编辑:
发现如果对每个绘图调用两次 gnuplot,那么根本不需要额外的文件。
\begin{filecontents*}{data1.dat}
5 1
6 1
3 1
3 1
7 1
8 1
3 1
8 1
7 1
9 1
5 1
\end{filecontents*}
\begin{filecontents*}{data2.dat}
12 2
14 2
12 2
8 2
22 2
22 2
12 2
12 2
7 2
12 2
2 2
\end{filecontents*}
\begin{filecontents*}{data3.dat}
20 3
20 3
21 3
20 3
22 3
21 3
20 3
24 3
22 3
21 3
20 3
\end{filecontents*}
\documentclass[tikz, border=1 cm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\usepgfplotslibrary{fillbetween}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
xmin=0, xmax=25,
ymin=0, ymax=4,
ytick={1,2,3},
yticklabels={Condition 1, Condition 2, Condition 3},
]
\addplot[draw=none, name path=p1, y filter/.expression={1+0.1*y}] gnuplot[raw gnuplot] {plot "data1.dat" using 1:2 smooth kdensity bandwidth 1.;};
\addplot[draw=none, name path=m1, y filter/.expression={1-0.1*y}] gnuplot[raw gnuplot] {plot "data1.dat" using 1:2 smooth kdensity bandwidth 1.;};
\addplot[red!50] fill between [of=p1 and m1];
\addplot[draw=none, name path=p2, y filter/.expression={2+0.1*y}] gnuplot[raw gnuplot] {plot "data2.dat" using 1:2 smooth kdensity bandwidth 1.;};
\addplot[draw=none, name path=m2, y filter/.expression={2-0.1*y}] gnuplot[raw gnuplot] {plot "data2.dat" using 1:2 smooth kdensity bandwidth 1.;};
\addplot[green!50] fill between [of=p2 and m2];
\addplot[draw=none, name path=p3, y filter/.expression={3+0.1*y}] gnuplot[raw gnuplot] {plot "data3.dat" using 1:2 smooth kdensity bandwidth 1.;};
\addplot[draw=none, name path=m3, y filter/.expression={3-0.1*y}] gnuplot[raw gnuplot] {plot "data3.dat" using 1:2 smooth kdensity bandwidth 1.;};
\addplot[blue!50] fill between [of=p3 and m3];
\end{axis}
\end{tikzpicture}
\end{document}