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
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.

🌐
GeeksforGeeks
geeksforgeeks.org › python › scipy-stats-skew-python
scipy stats.skew() | Python - GeeksforGeeks
February 11, 2019 - scipy.stats.skew(array, axis=0, bias=True) function calculates the skewness of the data set. skewness = 0 : normally distributed. skewness > 0 : more weight in the left tail of the distribution. skewness < 0 : more weight in the right tail of ...
🌐
SciPy
docs.scipy.org › doc › scipy › reference › generated › scipy.stats.Logistic.skewness.html
skewness — SciPy v1.18.0 Manual
scipy.stats.Logistic. Logistic.skewness(*, method=None)[source]# Skewness (standardized third moment) Parameters: method{None, ‘formula’, ‘general’, ‘transform’, ‘normalize’, ‘cache’} Method used to calculate the standardized third moment.
🌐
SciPy
docs.scipy.org › doc › scipy-1.16.1 › reference › generated › scipy.stats.Uniform.skewness.html
skewness — SciPy v1.16.1 Manual
Uniform.skewness(*, method=None)[source]# Skewness (standardized third moment) Parameters: method{None, ‘formula’, ‘general’, ‘transform’, ‘normalize’, ‘cache’} Method used to calculate the standardized third moment. Not all methods are available for all distributions.
🌐
Medium
medium.com › @whyamit404 › understanding-skewness-with-numpy-0ffb1b05dc71
Understanding Skewness with NumPy | by whyamit404 | Medium
February 26, 2025 - Here’s the thing: NumPy doesn’t have a built-in function to calculate skewness directly. But don’t worry — SciPy has your back with the scipy.stats.skew() function. The best part?
🌐
SciPy
docs.scipy.org › doc › scipy-1.16.2 › reference › generated › scipy.stats.Uniform.skewness.html
skewness — SciPy v1.16.2 Manual
Uniform.skewness(*, method=None)[source]# Skewness (standardized third moment) Parameters: method{None, ‘formula’, ‘general’, ‘transform’, ‘normalize’, ‘cache’} Method used to calculate the standardized third moment. Not all methods are available for all distributions.
Find elsewhere
🌐
SciPy
docs.scipy.org › doc › scipy › reference › generated › scipy.stats.skewtest.html
skewtest — SciPy v1.18.0 Manual
This function tests the null hypothesis that the skewness of the population that the sample was drawn from is the same as that of a corresponding normal distribution.
🌐
Python Guides
pythonguides.com › python-scipy-stats-skew
Python SciPy Stats Skew
June 23, 2025 - This example demonstrates how different distributions have different skewness values, and how we can use D’Agostino’s K-squared test (which incorporates skewness) to assess normality. ... from scipy import stats import numpy as np import matplotlib.pyplot as plt # Generate data from a skewed normal distribution # Simulating average daily temperatures in New York throughout the year alpha = -3 # Negative for left skew (colder days are more extreme) data = stats.skewnorm.rvs(alpha, loc=60, scale=15, size=365) # loc=60 (mean), scale=15 (std) # Calculate the skewness skewness = stats.skew(data
🌐
SciPy
docs.scipy.org › doc › scipy-1.12.0 › reference › generated › scipy.stats.skewtest.html
scipy.stats.skewtest — SciPy v1.12.0 Manual
This function tests the null hypothesis that the skewness of the population that the sample was drawn from is the same as that of a corresponding normal distribution.
🌐
SciPy
docs.scipy.org › doc › scipy › reference › generated › scipy.stats.Normal.skewness.html
skewness — SciPy v1.15.2 Manual
Normal.skewness(*, method=None)[source]# Skewness (standardized third moment) Parameters: method{None, ‘formula’, ‘general’, ‘transform’, ‘normalize’, ‘cache’} Method used to calculate the standardized third moment. Not all methods are available for all distributions.
🌐
SciPy
docs.scipy.org › doc › scipy-0.15.1 › reference › generated › scipy.stats.skew.html
scipy.stats.skew — SciPy v0.15.1 Reference Guide
January 18, 2015 - For normally distributed data, the skewness should be about 0. A skewness value > 0 means that there is more weight in the left tail of the distribution.
🌐
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 - There are various ways to determine the skewness of the graph. The most famous is Fisher-Pearson Coefficient. This mathematical formula is being used in the scipy also It is based on the central moments.
🌐
SciPy
docs.scipy.org › doc › scipy › tutorial › stats › hypothesis_skewtest.html
Skewness test — SciPy v1.18.0 Manual
This function tests the null hypothesis that the skewness of the population that the sample was drawn from is the same as that of a corresponding normal distribution.
🌐
SciPy
docs.scipy.org › doc › scipy-1.16.1 › reference › generated › scipy.stats.skewtest.html
skewtest — SciPy v1.16.1 Manual
This function tests the null hypothesis that the skewness of the population that the sample was drawn from is the same as that of a corresponding normal distribution.