Raincloud plots combine a filled KDE curve with a boxplot and stripplot, resembling a raincloud. They provide a clear visualization of data distribution and density, surpassing the limitations of histogram binning.
Here is a basic function to plot individual horizontal rainclouds in python as an alternative to ptitprince raincloud package as it needs seaborn 0.11.
This function requires an upper version of seaborn. Use it or edit it.
pandas==2.2.2
numpy==2.0.0
seaborn==0.13.2
matplotlib==3.9.0
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
# Create custom raincloud plot ---------------------------------------------------
def rcloud(data, title, xlabel, color='skyblue', ylabel='Density', figsize=None, ax=None):
"""
Create a raincloud plot combining KDE plot, boxplot, and stripplot.
Parameters:
ax : Axes object where the plot will be drawn.
data : array-like Data to be plotted.
title : str Title of the plot.
xlabel : str Label for the x-axis.
color : str, optional, Color to be used for plotting.
ylabel : str, optional, Label for the y-axis.
figsize : tuple, optional, size of figure - If None, defaults to matplotlib's default.
Returns:
None
"""
# Create a figure with specified figsize if provided
if figsize:
fig, ax = plt.subplots(figsize=figsize)
# Plot KDE plot
sns.kdeplot(data=data, ax=ax, fill=True, color=color, alpha=1, bw_adjust=1)
# Get y-axis limits for further adjustments
y_min, y_max = ax.get_ylim()
# Plot boxplot
sns.boxplot(x=data, ax=ax, fill=True, width=y_max/16, color=color, linecolor='#454D4D', linewidth=1,
fliersize=0, showcaps=False, notch=True)
# Adjust y-axis limits and create a twin axis for stripplot
ax.set_ylim(-y_max, y_max); ax2 = ax.twinx(); jitter = 0.85 * y_max
# Plot stripplot on the twin axis
sns.stripplot(x=data, ax=ax2, size=5, color=color, jitter=jitter, alpha=0.75)
# Set y-axis limits for the twin axis
ax2.set_ylim(-y_max, 3*y_max)
# Set plot title and axis labels with specified fontsize
ax.set_title(title, fontsize=9)
ax.set_xlabel(xlabel, fontsize=7)
ax.set_ylabel(ylabel, fontsize=7)
# Set tick parameters for both axes
ax.tick_params(axis='both', which='major', labelsize=7)
# Add gridlines to the plot with specified linestyle and linewidth
ax.grid(True, linestyle=':', linewidth=0.5)
# Load the penguins dataset
penguins = sns.load_dataset("penguins")
# Call raincloud plot function with penguins dataset
raincloud(
data=penguins['flipper_length_mm'],
title='Raincloud Plot of Flipper Length',
xlabel='Flipper Length (mm)',
ylabel='Density',
figsize=(6,3),
color='skyblue'
)
# Show plot
plt.tight_layout()
plt.show()
This raincloud plot uses axes so You can make subplots like this:
However You can test ptitprince version which is more customizable. Check it https://github.com/pog87/PtitPrince