Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pyplot: draw a smooth curve over a histogram

There is a histogram rendered using a DataFrame as a data source:

import seaborn as sns
import matplotlib.pyplot as plt

plt.rcParams["figure.figsize"] = (14,14)

df['rawValue'].hist(bins=100)
    
plt.show()

enter image description here

Q. How to add a smooth curve in front of the histogram? (The curve shares the same data source as the histogram)?

P.S. Just a depiction of what is wanted (purely schematic):

enter image description here

like image 447
Denis Kulagin Avatar asked Sep 10 '25 05:09

Denis Kulagin


1 Answers

To my knowledge, the most common way of doing this is to use kernel density estimation. You can read about how it can be implemented in Python here and here. And here are a couple examples of how to draw a KDE over a histogram using pandas and seaborn:


Import packages and create sample dataset for both examples

import numpy as np                 # v 1.19.2
import pandas as pd                # v 1.1.3
import matplotlib.pyplot as plt    # v 3.3.2
import seaborn as sns              # v 0.11.0

# Create sample dataset
rng = np.random.default_rng(seed=123)  # random number generator
df = pd.DataFrame(dict(variable = rng.normal(size=1000)))

Pandas

# Plot pandas histogram from dataframe with df.plot.hist (not df.hist)
ax = df['variable'].plot.hist(bins=20, density=True, edgecolor='w', linewidth=0.5)

# Save default x-axis limits for final formatting because the pandas kde
# plot uses much wider limits which usually decreases readability
xlim = ax.get_xlim()

# Plot pandas KDE
df['variable'].plot.density(color='k', alpha=0.5, ax=ax) # same as df['var'].plot.kde()

# Reset x-axis limits and edit legend and add title
ax.set_xlim(xlim)
ax.legend(labels=['KDE'], frameon=False)
ax.set_title('Pandas histogram overlaid with KDE', fontsize=14, pad=15)

plt.show()

pandas_kde


Seaborn

# Plot seaborn histogram overlaid with KDE
ax = sns.histplot(data=df['variable'], bins=20, stat='density', alpha= 1, kde=True,
                  edgecolor='white', linewidth=0.5,
                  line_kws=dict(color='black', alpha=0.5, linewidth=1.5, label='KDE'))
ax.get_lines()[0].set_color('black') # edit line color due to bug in sns v 0.11.0

# Edit legemd and add title
ax.legend(frameon=False)
ax.set_title('Seaborn histogram overlaid with KDE', fontsize=14, pad=15)

plt.show()

seaborn_kde

like image 186
Patrick FitzGerald Avatar answered Sep 12 '25 18:09

Patrick FitzGerald