These functions calculate moments of the probability density distribution (that's why it takes only one parameter) and doesn't care about the "functional form" of the values.

These are meant for "random datasets" (think of them as measures like mean, standard deviation, variance):

import numpy as np
from scipy.stats import kurtosis, skew

x = np.random.normal(0, 2, 10000)   # create random values based on a normal distribution

print( 'excess kurtosis of normal distribution (should be 0): {}'.format( kurtosis(x) ))
print( 'skewness of normal distribution (should be 0): {}'.format( skew(x) ))

which gives:

excess kurtosis of normal distribution (should be 0): -0.024291887786943356
skewness of normal distribution (should be 0): 0.009666157036010928

changing the number of random values increases the accuracy:

x = np.random.normal(0, 2, 10000000)

Leading to:

excess kurtosis of normal distribution (should be 0): -0.00010309478605163847
skewness of normal distribution (should be 0): -0.0006751744848755031

In your case the function "assumes" that each value has the same "probability" (because the values are equally distributed and each value occurs only once) so from the point of view of skew and kurtosis it's dealing with a non-gaussian probability density (not sure what exactly this is) which explains why the resulting values aren't even close to 0:

import numpy as np
from scipy.stats import kurtosis, skew

x_random = np.random.normal(0, 2, 10000)

x = np.linspace( -5, 5, 10000 )
y = 1./(np.sqrt(2.*np.pi)) * np.exp( -.5*(x)**2  )  # normal distribution

import matplotlib.pyplot as plt

f, (ax1, ax2) = plt.subplots(1, 2)
ax1.hist(x_random, bins='auto')
ax1.set_title('probability density (random)')
ax2.hist(y, bins='auto')
ax2.set_title('(your dataset)')
plt.tight_layout()

Answer from MSeifert on Stack Overflow
🌐
SciPy
docs.scipy.org › doc › scipy › reference › generated › scipy.stats.kurtosistest.html
kurtosistest — SciPy v1.18.0 Manual
This function tests the null hypothesis that the kurtosis of the population from which the sample was drawn is that of the normal distribution.
Top answer
1 of 2
51

These functions calculate moments of the probability density distribution (that's why it takes only one parameter) and doesn't care about the "functional form" of the values.

These are meant for "random datasets" (think of them as measures like mean, standard deviation, variance):

import numpy as np
from scipy.stats import kurtosis, skew

x = np.random.normal(0, 2, 10000)   # create random values based on a normal distribution

print( 'excess kurtosis of normal distribution (should be 0): {}'.format( kurtosis(x) ))
print( 'skewness of normal distribution (should be 0): {}'.format( skew(x) ))

which gives:

excess kurtosis of normal distribution (should be 0): -0.024291887786943356
skewness of normal distribution (should be 0): 0.009666157036010928

changing the number of random values increases the accuracy:

x = np.random.normal(0, 2, 10000000)

Leading to:

excess kurtosis of normal distribution (should be 0): -0.00010309478605163847
skewness of normal distribution (should be 0): -0.0006751744848755031

In your case the function "assumes" that each value has the same "probability" (because the values are equally distributed and each value occurs only once) so from the point of view of skew and kurtosis it's dealing with a non-gaussian probability density (not sure what exactly this is) which explains why the resulting values aren't even close to 0:

import numpy as np
from scipy.stats import kurtosis, skew

x_random = np.random.normal(0, 2, 10000)

x = np.linspace( -5, 5, 10000 )
y = 1./(np.sqrt(2.*np.pi)) * np.exp( -.5*(x)**2  )  # normal distribution

import matplotlib.pyplot as plt

f, (ax1, ax2) = plt.subplots(1, 2)
ax1.hist(x_random, bins='auto')
ax1.set_title('probability density (random)')
ax2.hist(y, bins='auto')
ax2.set_title('(your dataset)')
plt.tight_layout()

2 of 2
12

You are using as data the "shape" of the density function. These functions are meant to be used with data sampled from a distribution. If you sample from the distribution, you will obtain sample statistics that will approach the correct value as you increase the sample size. To plot the data, I would recommend a histogram.

%matplotlib inline
import numpy as np
import pandas as pd
from scipy.stats import kurtosis
from scipy.stats import skew

import matplotlib.pyplot as plt

plt.style.use('ggplot')

data = np.random.normal(0, 1, 10000000)
np.var(data)

plt.hist(data, bins=60)

print("mean : ", np.mean(data))
print("var  : ", np.var(data))
print("skew : ",skew(data))
print("kurt : ",kurtosis(data))

Output:

mean :  0.000410213500847
var  :  0.999827716979
skew :  0.00012294118186476907
kurt :  0.0033554829466604374

Unless you are dealing with an analytical expression, it is extremely unlikely that you will obtain a zero when using data.

🌐
Towards Data Science
towardsdatascience.com › home › latest › calculate kurtosis in python (with examples)
Calculate Kurtosis in Python (with Examples) | Towards Data Science
March 5, 2025 - Where skewness focuses on the ... of the tails), kurtosis measures whether there are extreme values in either of the tails (or simply if the tails are heavy or light). To continue following this tutorial we will need the following Python library: ...
🌐
GeeksforGeeks
geeksforgeeks.org › python › scipy-stats-kurtosis-function-python
scipy stats.kurtosis() function | Python - GeeksforGeeks
June 20, 2022 - bias : Bool; calculations are corrected for statistical bias, if set to False. Returns : Kurtosis value of the normal distribution for the data set.
Find elsewhere
🌐
GeeksforGeeks
geeksforgeeks.org › data science › how-to-calculate-skewness-and-kurtosis-in-python
Understanding Skewness and Kurtosis in Python - GeeksforGeeks
We import the kurtosis function from SciPy, which provides an inbuilt method to calculate kurtosis.
Published: May 2, 2026
🌐
SciPy
docs.scipy.org › doc › scipy › tutorial › stats › hypothesis_kurtosistest.html
Kurtosis test — SciPy v1.17.0 Manual
The kurtosis test scipy.stats.kurtosistest function tests the null hypothesis that the kurtosis of the population from which the sample was drawn is that of the normal distribution.
🌐
SciPy
docs.scipy.org › doc › scipy-1.16.1 › reference › generated › scipy.stats.Normal.kurtosis.html
kurtosis — SciPy v1.16.1 Manual
By default, this is the standardized fourth moment, also known as the “non-excess” or “Pearson” kurtosis (e.g. the kurtosis of the normal distribution is 3). The “excess” or “Fisher” kurtosis (the standardized fourth moment minus 3) is available via the convention parameter.
🌐
Medium
medium.com › @pritul.dave › everything-about-moments-skewness-and-kurtosis-using-python-numpy-df305a193e46
Everything about Moments, Skewness, and Kurtosis in python | by Pritul Dave :) | Medium
July 29, 2022 - arr3 = np.array([-40,-45,-50,-10,-5,-1,0,1,5,10,]) fun_kurtosis(arr3)>>> Mean: -13.5 >>> Median: -3.0 >>> Beta 2: 1.823188010212515 >>> Gamma 2: -1.176811989787485from scipy.stats import kurtosiskurtosis(arr3)>>> -1.176811989787485 ·
🌐
YouTube
youtube.com › watch
How to Compute Kurtosis in Python with Scipy & Numpy - YouTube
In this tutorial, you’ll learn how to calculate kurtosis in Python step-by-step using SciPy and NumPy. Understanding kurtosis helps you evaluate the tailedne...
Published: October 7, 2024
🌐
GeeksforGeeks
geeksforgeeks.org › python › how-to-calculate-skewness-and-kurtosis-in-python
How to Calculate Skewness and Kurtosis in Python? - GeeksforGeeks
January 31, 2026 - We import the kurtosis function from SciPy, which provides an inbuilt method to calculate kurtosis.
🌐
SciPy
docs.scipy.org › doc › scipy-1.13.1 › reference › generated › scipy.stats.kurtosistest.html
scipy.stats.kurtosistest — SciPy v1.13.1 Manual
This function tests the null hypothesis that the kurtosis of the population from which the sample was drawn is that of the normal distribution.
🌐
Kaggle
kaggle.com › code › rhythmcam › scipy-stats-basic-kurtosis-usage
[scipy.stats Basic]kurtosis usage
December 15, 2021 - outlier data => kurtosis > 3solver => log process => kurtosis < 3 · This Notebook has been released under the Apache 2.0 open source license. Input1 file · arrow_right_alt · Output0 files · arrow_right_alt · Logs19.7 second run - successful · arrow_right_alt ·