0

Since I couldn't find any instructions to make a violin plot in the pgfplot manual, I am making a box-plot and adding the corresponding points on the plot. This tends to be more transparent with the data visualisation (See image below).

Boxplot_image

Is there a way so the points with the same x-axis value spread across the y-axis, but within the limits of the box-width? This is so they don't overlap.

Also, for some reason, I am unable to change the colours of the marks!

Here is my MWE:

\documentclass[margin=1cm]{standalone}

%Required packages
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\usepgfplotslibrary{statistics}
\usepgfplotslibrary{groupplots}

\begin{document}

\begin{tikzpicture}
\begin{axis}[
every y tick label/.append style={font=\footnotesize},
every x tick label/.append style={font=\footnotesize},
yticklabel style={align=center},
ytick={1,2,3},
yticklabels={Condition 1, Condition 2, Condition 3},
%boxplot/variable width,
]
\addplot+ [% Condition1:
boxplot prepared={
lower whisker=3, lower quartile=4,
median=6,
upper quartile=7.5, upper whisker=9},
black, solid, thick] coordinates {};

\addplot [%Corresponding points for Condition1
scatter, only marks, mark=x, mark options={fill=black, color=black}] table{
x   y
5   1
6   1
3   1
3   1
7   1
8   1
3   1
8   1
7   1
9   1
5   1
};

%%
%%Starting condition 2

\addplot+ [% Condition2:
boxplot prepared={
lower whisker=2, lower quartile=10,
median=12,
upper quartile=13, upper whisker=22},
black, solid] coordinates {};

\addplot [%Corresponding points for Condition2
scatter, only marks, mark=*, mark options={fill=black, color=black}] table{
x   y
12  2
14  2
12  2
8   2
22  2
22  2
12  2
12  2
7   2
12  2
2   2
};

%%Starting Condition 3
\addplot+ [% Condition3:
boxplot prepared={
lower whisker=20, lower quartile=20,
median=21,
upper quartile=21.5, upper whisker=24},
black, solid] coordinates {};

\addplot [%Corresponding points for Condition2
scatter, only marks, mark=o, mark options={fill=black, color=black}] table{
x   y
20  3
20  3
21  3
20  3
22  3
21  3
20  3
24  3
22  3
21  3
20  3
};
\end{axis}
\end{tikzpicture}
\end{document}
1

1 Answer 1

1

You can change the y values when reading in the table with y expr or in the plot itself with y filter/.expression, but there is no direct way to make the points automatically spread out. That would mean that the plot routine would be aware of previous points. The only way I see it could be done is to load the data using pgfplotstable and then loop over the table extracting values, and creating a new column with the new y values.

It would be much easier just to write the y values you really want. -or generate the values in the program from where they came.

(An other stupid way with more manual work would be to make a stacked scatter plot, but that would mean making a new \addplot for each duplicate x value.)

Here I am only faking it by making the y-values dependent on the line number in the tables.

\documentclass[tikz, border=1cm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\usepgfplotslibrary{statistics}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
every y tick label/.append style={font=\footnotesize},
every x tick label/.append style={font=\footnotesize},
yticklabel style={align=center},
ytick={1,2,3},
yticklabels={Condition 1, Condition 2, Condition 3},
]
%%Starting condition 1
\addplot+[% Condition1:
boxplot prepared={
lower whisker=3, lower quartile=4,
median=6,
upper quartile=7.5, upper whisker=9},
black, solid, thick] coordinates {};

\addplot[%Corresponding points for Condition1
only marks, mark=x, mark color=black] table[y expr={0.7+0.05*\lineno}]{
x   y
5   1
6   1
3   1
3   1
7   1
8   1
3   1
8   1
7   1
9   1
5   1
};

%%Starting condition 2
\addplot+[% Condition2:
boxplot prepared={
lower whisker=2, lower quartile=10,
median=12,
upper quartile=13, upper whisker=22},
black, solid] coordinates {};

\addplot[%Corresponding points for Condition2
only marks, mark=*, mark color=black] table[y expr={1.7+0.05*\lineno}]{
x   y
12  2
14  2
12  2
8   2
22  2
22  2
12  2
12  2
7   2
12  2
2   2
};

%%Starting Condition 3
\addplot+[% Condition3:
boxplot prepared={
lower whisker=20, lower quartile=20,
median=21,
upper quartile=21.5, upper whisker=24},
black, solid] coordinates {};

\addplot[%Corresponding points for Condition3
only marks, mark=o, mark color=black] table[y expr={2.7+0.05*\lineno}]{
x   y
20  3
20  3
21  3
20  3
22  3
21  3
20  3
24  3
22  3
21  3
20  3
};
\end{axis}
\end{tikzpicture}
\end{document}

Graph with three box plots and scatter points

3
  • With regards to the posted solution, can you now apply y expr conditionally to those points which share the came x axis coordinate? That way, unique points can remain along a single line while the others can disperse. (This is just a request though) Commented Oct 26, 2022 at 7:14
  • No. y expr has no way of knowing if the point is unique. See p. 50 in the manual "Only data within the same row can be used where columns are referenced with \thisrow{⟨column name⟩} or \thisrowno{⟨column index⟩}." Commented Oct 26, 2022 at 7:28
  • Thank you so much for patiently answering! Commented Oct 26, 2022 at 10:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .