A histogram with kernel density estimate (KDE) overlay combines discrete binning with continuous density estimation to visualize the distribution of continuous data. The histogram bars show frequency counts in each bin while the smooth KDE curve reveals the underlying probability density, making it easier to perceive the true shape of the distribution without binning artifacts.

""" anyplot.ai
histogram-kde: Histogram with KDE Overlay
Library: letsplot 4.9.0 | Python 3.13.13
Quality: 87/100 | Updated: 2026-05-06
"""
import os
from pathlib import Path
import numpy as np
import pandas as pd
from lets_plot import *
LetsPlot.setup_html()
# Theme tokens
THEME = os.getenv("ANYPLOT_THEME", "light")
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F"
BRAND = "#009E73" # Okabe-Ito position 1
# Data - Simulated stock daily returns (realistic financial scenario)
np.random.seed(42)
returns = np.concatenate(
[np.random.normal(0.001, 0.015, 400), np.random.normal(-0.02, 0.03, 50), np.random.normal(0.02, 0.025, 50)]
)
returns = returns * 100
df = pd.DataFrame({"Daily Return (%)": returns})
# Plot
anyplot_theme = (
theme(
plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),
panel_background=element_rect(fill=PAGE_BG),
panel_grid_major=element_line(
color=INK_SOFT, size=0.3
),
panel_grid_minor=element_blank(),
axis_title=element_text(size=20, color=INK),
axis_text=element_text(size=16, color=INK_SOFT),
axis_line=element_line(color=INK_SOFT, size=0.5),
plot_title=element_text(size=24, color=INK),
legend_background=element_rect(
fill=ELEVATED_BG, color=INK_SOFT
),
legend_text=element_text(size=16, color=INK_SOFT),
legend_title=element_text(size=16, color=INK),
)
+ theme_minimal()
)
plot = (
ggplot(df, aes(x="Daily Return (%)"))
+ geom_histogram(
aes(y="..density.."),
bins=35,
fill=BRAND,
alpha=0.5,
color=BRAND,
size=0.5,
)
+ geom_density(
color=INK_SOFT, size=1.5, fill="rgba(0,0,0,0)"
)
+ labs(
x="Daily Return (%)", y="Density", title="histogram-kde · letsplot · anyplot.ai"
)
+ ggsize(1600, 900)
+ anyplot_theme
)
# Save
output_dir = Path(__file__).parent
ggsave(plot, str(output_dir / f"plot-{THEME}.png"), scale=3)
ggsave(plot, str(output_dir / f"plot-{THEME}.html"))
Part of Histogram with KDE Overlay on anyplot.ai.