Skip to content

Instantly share code, notes, and snippets.

@ScinDBad
Last active July 5, 2024 10:06
Show Gist options
  • Save ScinDBad/bb0006981c9a9334ec06709226b26e65 to your computer and use it in GitHub Desktop.
Save ScinDBad/bb0006981c9a9334ec06709226b26e65 to your computer and use it in GitHub Desktop.
Customize raincloud plot

Raincloud plot

rc python da (1)

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.

Requirements (Python 3.11.8)

pandas==2.2.2
numpy==2.0.0
seaborn==0.13.2
matplotlib==3.9.0

Function definition

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) 

Example

# 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()

image

This raincloud plot uses axes so You can make subplots like this:

image

However You can test ptitprince version which is more customizable. Check it https://github.com/pog87/PtitPrince

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment