using CairoMakie
using DataFrames
using Statistics
using RandomViolin Plot (Julia)
A violin plot combines box plot statistics with kernel density estimation to show data distributions. Julia’s CairoMakie makes it straightforward to create violin plots for comparing gene expression, biomarker levels, or clinical measurements across groups.
Example

Setup
- System Requirements: Cross-platform (Linux/MacOS/Windows)
- Programming Language: Julia
- Dependencies:
CairoMakie,DataFrames,Statistics
Data Preparation
Random.seed!(42)
n_per = 80
groups = vcat(fill("Tumor", n_per), fill("Normal", n_per), fill("Adjacent", n_per))
expression = vcat(
randn(n_per) .* 1.5 .+ 8,
randn(n_per) .* 1.2 .+ 5,
randn(n_per) .* 1.8 .+ 6.5
)
group_idx = vcat(fill(1, n_per), fill(2, n_per), fill(3, n_per))
df = DataFrame(Group=groups, Expression=expression, GroupIdx=group_idx)240×3 DataFrame
215 rows omitted
| Row | Group | Expression | GroupIdx |
|---|---|---|---|
| String | Float64 | Int64 | |
| 1 | Tumor | 7.45496 | 1 |
| 2 | Tumor | 8.37761 | 1 |
| 3 | Tumor | 7.52752 | 1 |
| 4 | Tumor | 7.53312 | 1 |
| 5 | Tumor | 9.22446 | 1 |
| 6 | Tumor | 8.71511 | 1 |
| 7 | Tumor | 6.71067 | 1 |
| 8 | Tumor | 5.79607 | 1 |
| 9 | Tumor | 4.8285 | 1 |
| 10 | Tumor | 8.06567 | 1 |
| 11 | Tumor | 6.762 | 1 |
| 12 | Tumor | 9.26043 | 1 |
| 13 | Tumor | 8.65083 | 1 |
| ⋮ | ⋮ | ⋮ | ⋮ |
| 229 | Adjacent | 8.67822 | 3 |
| 230 | Adjacent | 5.35136 | 3 |
| 231 | Adjacent | 6.22416 | 3 |
| 232 | Adjacent | 3.53355 | 3 |
| 233 | Adjacent | 8.33217 | 3 |
| 234 | Adjacent | 6.73736 | 3 |
| 235 | Adjacent | 11.0713 | 3 |
| 236 | Adjacent | 6.77344 | 3 |
| 237 | Adjacent | 7.34419 | 3 |
| 238 | Adjacent | 5.31451 | 3 |
| 239 | Adjacent | 5.72756 | 3 |
| 240 | Adjacent | 3.46341 | 3 |
Visualization
Basic Violin Plot
fig = Figure(size=(700, 500))
ax = Axis(fig[1,1], xlabel="Group", ylabel="Expression Level",
title="Gene Expression Distribution",
xticks=(1:3, ["Tumor", "Normal", "Adjacent"]))
violin!(ax, df.GroupIdx, df.Expression, color=(:steelblue, 0.7))
figGrouped Violin with Box Plot Overlay
fig2 = Figure(size=(700, 500))
ax2 = Axis(fig2[1,1], xlabel="Group", ylabel="Expression Level",
title="Violin + Box Plot",
xticks=(1:3, ["Tumor", "Normal", "Adjacent"]))
colors = [:red, :steelblue, :green]
for (i, g) in enumerate(["Tumor", "Normal", "Adjacent"])
mask = df.Group .== g
vals = df.Expression[mask]
violin!(ax2, fill(i, sum(mask)), vals, color=(colors[i], 0.4), side=:left)
boxplot!(ax2, fill(i, sum(mask)), vals, color=(colors[i], 0.7), width=0.3)
end
fig2Half Violin (Raincloud) Plot
fig3 = Figure(size=(800, 500))
ax3 = Axis(fig3[1,1], xlabel="Group", ylabel="Expression Level",
title="Raincloud Plot",
xticks=(1:3, ["Tumor", "Normal", "Adjacent"]))
for (i, g) in enumerate(["Tumor", "Normal", "Adjacent"])
mask = df.Group .== g
vals = df.Expression[mask]
violin!(ax3, fill(i, sum(mask)), vals, color=(colors[i], 0.5), side=:right)
scatter!(ax3, fill(i, sum(mask)) .- 0.15 .+ randn(sum(mask)) .* 0.03,
vals, color=(colors[i], 0.3), markersize=5)
end
fig3References
- Danisch, S., & Krumbiegel, J. (2021). Makie.jl: Flexible high-performance data visualization for Julia. JOSS, 6(65), 3349.
