Introduction
A box plot tells you the median and quartiles, but it can hide whether a group's distribution is actually bimodal, skewed, or has a fundamentally different shape than another group's. PlotDensityByGroup renders overlapping kernel density estimate curves for a continuous variable, split by category, so shape differences — not just summary statistics — are visible between groups.
Teaching Note
Density plots are essential for:
- Epidemiology: Comparing the distribution of incubation periods across different viral strains.
- Healthcare: Analyzing the distribution of patient recovery times for various clinical treatments.
- Data Science: Comparing the probability density of model prediction errors across different datasets.
- Public Health: Monitoring the distribution of particulate matter concentrations across urban regions.
- Finance: Analyzing the probability density of daily returns for multiple investment portfolios.
- Operations: Examining the distribution of processing times across different manufacturing shifts.
- Social Science: Visualizing the distribution of standardized test scores across demographic segments.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
dataframerequired | pd.DataFrame | — | The pandas DataFrame containing the numeric values and categorical grouping variable. |
value_column_namerequired | str | — | The name of the continuous numeric column to be plotted on the x-axis. |
grouping_column_namerequired | str | — | The name of the categorical column used to separate the data into different density curves. |
color_palette | str | 'Set2' | The name of the seaborn color palette to use for the density curves. Defaults to 'Set2'. |
show_legend | bool | True | Whether to display the legend mapping colors to grouping levels. Defaults to True. |
figure_size | tuple | (8, 6) | The dimensions of the output figure as a (width, height) tuple in inches. Defaults to (8, 6). |
title_for_plot | str | None | The primary title text displayed at the top of the chart. Defaults to None. |
subtitle_for_plot | str | None | Descriptive subtitle text displayed below the main title. Defaults to None. |
caption_for_plot | str | None | Explanatory text or notes displayed at the bottom of the plot. Defaults to None. |
data_source_for_plot | str | None | Text identifying the source of the data, appended to the caption. Defaults to None. |
show_y_axis | bool | False | Whether to display the y-axis (density scale). Defaults to False. |
title_y_indent | float | 1.1 | Vertical offset for the title position relative to the axes. Defaults to 1.1. |
subtitle_y_indent | float | 1.05 | Vertical offset for the subtitle position relative to the axes. Defaults to 1.05. |
caption_y_indent | float | -0.15 | Vertical offset for the caption position relative to the axes. Defaults to -0.15. |
filepath_to_save_plot | str | None | The local path (ending in .png or .jpg) where the plot should be exported. If None, the file is not saved. Defaults to None. |
Returns
None — the function displays the density plot using matplotlib and optionally saves it to disk.
Example
python
from analysistoolbox.visualizations import PlotDensityByGroup
import pandas as pd
# Epidemiology: distribution of incubation periods by strain
incubation_df = pd.DataFrame({
'Strain': ['Strain A'] * 100 + ['Strain B'] * 100,
'Days': [2, 3, 3, 4, 5, 2.5, 3.5] * 28 + [5, 6, 7, 8, 5.5, 6.5, 7.5] * 28
})
PlotDensityByGroup(
incubation_df, 'Days', 'Strain',
title_for_plot="Viral Incubation Period Density",
subtitle_for_plot="Comparison of time to symptom onset between two dominant strains"
)