Mastering Density Plots: A Smooth Guide

Visualizing Continuous Distributions in ggplot2

Author

Abdullah Al Shamim

Published

February 8, 2026

Introduction

A Density Plot is a representation of the distribution of a continuous variable. It is essentially a smoothed version of a histogram and is used to estimate the probability density function of a variable.


1. Basic Density Plot

The foundation of a density plot in R is the geom_density() function. It provides a quick look at where the data points are concentrated.

Code
library(tidyverse)

# Basic Density Plot
iris %>% 
  ggplot(aes(x = Sepal.Length)) +
  geom_density() +
  labs(title = "Basic Density Plot of Sepal Length",
       subtitle = "A systemic look at data probability density",
       x = "Sepal Length (cm)",
       y = "Density") +
  theme_minimal()


2. Styling & Customization

To make the plot professional, we add color, transparency, and border lines.

Code
iris %>%
  ggplot(aes(x = Sepal.Length)) +
  geom_density(fill = "#A88EF2",         # Fill color
               alpha = 0.5,              # Transparency
               color = "black",          # Border color
               linewidth = 0.7) +        # Line thickness
  labs(title = "Customized Density Plot",
       x = "Sepal Length (cm)",
       y = "Density") +
  theme_classic()


3. Grouped Comparisons (Multiple Densities)

Comparing multiple groups (e.g., Species) allows us to see how distributions overlap or differ across categories.

Code
iris %>%
  ggplot(aes(x = Sepal.Length, fill = Species)) + 
  geom_density(alpha = 0.5) +
  labs(title = "Sepal Length Distribution by Species",
       subtitle = "Comparing flower species characteristics",
       x = "Sepal Length (cm)",
       y = "Density") +
  scale_fill_brewer(palette = "Set1") + 
  theme_minimal()


4. Smoothness Control (Adjusting Bandwidth)

The adjust parameter acts as a “zoom” for detail.

Code
iris %>%
  ggplot(aes(x = Sepal.Length)) +
  geom_density(adjust = 0.5,               # Smaller value = More detail
               fill = "lightblue",
               alpha = 0.7) +
  labs(title = "High-Detail Density Plot",
       subtitle = "Adjust = 0.5 (Smaller bandwidth reveals more peaks)",
       x = "Sepal Length (cm)") +
  theme_light()


5. Pro-Tip: The Histogram + Density Combo

Seeing the actual bins (Histogram) alongside the trend (Density) provides the most complete picture of your data.

Code
iris %>%
  ggplot(aes(x = Sepal.Length)) +
  # Map histogram y-axis to density scale
  geom_histogram(aes(y = after_stat(density)), 
                 bins = 30,
                 fill = "lightblue",
                 color = "white") +
  geom_density(color = "red", linewidth = 1) +
  theme_test() +
  labs(title = "Density + Histogram Combination",
       subtitle = "Overlaying smooth trends on raw data counts",
       x = "Sepal Length (cm)")


Systemic Summary Toolkit

Feature Function/Parameter Use Case
Fill fill = "color" Colors the area under the curve.
Transparency alpha = 0.5 Essential for overlapping multiple groups.
Smoothing adjust = n n < 1 for detail; n > 1 for smoothness.
Combination after_stat(density) Aligns histogram scale with density curve.