Kurtosis measures the tail heaviness of a distribution — its tendency to produce extreme values. It’s the fourth standardized moment:

The fourth power amplifies large deviations more than the cube does (the cube was for Skewness), so kurtosis is dominated by the tails of the distribution. A distribution with rare but very large excursions has high kurtosis; one whose values are all clustered tightly around the mean has low kurtosis.

The numerical reference value is 3, which is the kurtosis of a normal distribution under this formula. Distributions are classified by how their kurtosis compares to 3:

  • Leptokurtic — kurtosis . Heavier tails than a normal distribution, more extreme values, a sharper central peak. Lepto- means thin, referring to the thin sharp peak.
  • Mesokurtic — kurtosis . Same tail behaviour as a normal distribution. Meso- means middle.
  • Platykurtic — kurtosis . Lighter tails, fewer extreme values, a flatter central peak. Platy- means flat — a flat-headed distribution.

A mnemonic: the Greek prefixes describe the peak shape — thin peak, middle peak, flat peak. The threshold value is 3 in each case.

In Feature extraction from signals, kurtosis captures the peakiness of the signal within a window. A clean QRS complex in an ECG heartbeat is very peaky — high kurtosis. A flat baseline between heartbeats is not peaky — low kurtosis. The kurtosis varies dramatically as the rolling window passes over different parts of the signal, which makes it a useful feature for classifiers trying to detect heartbeat onsets or distinguish heartbeat morphologies.

Kurtosis is the fourth of the first four moments used as standard signal features, alongside the mean, Standard deviation, and Skewness.

In Pandas: df['col'].kurt() for the whole column, df['col'].rolling(N).kurt() for a rolling window. In SciPy: scipy.stats.kurtosis(arr).

There’s a notational subtlety. Some sources define excess kurtosis as (kurtosis) − 3, which makes a normal distribution have excess kurtosis 0 instead of kurtosis 3. SciPy’s kurtosis() returns excess kurtosis by default. Pandas’ .kurt() also returns excess kurtosis. So df['col'].kurt() > 0 corresponds to leptokurtic, < 0 to platykurtic — different threshold from the formula above. The convention varies; the underlying concept doesn’t.