Документация Python неофициальный перевод
Содержание страницы

statistics – Функции математической статистикиstatistics – Mathematical statistics functions

Добавлено в версии 3.4.

Исходный код: Lib/statistics.py


Этот модуль предоставляет функции для вычисления математической статистики числовых данных (со значениями Real).

Модуль не предназначен для конкуренции со сторонними библиотеками, такими как NumPy, SciPy, или проприетарными полнофункциональными пакетами статистики, ориентированными на профессиональных статистиков, такими как Minitab, SAS и Matlab. Он рассчитан на уровень графических и научных калькуляторов.

Если не указано иное, эти функции поддерживают int, float, Decimal и Fraction. Поведение с другими типами (будь то в числовой иерархии или нет) в настоящее время не поддерживается. Коллекции со смешанными типами также не определены и зависят от реализации. Если входные данные состоят из смешанных типов, можно использовать map() для обеспечения согласованного результата, например: map(float, input_data).

В некоторых наборах данных используются значения NaN (не число) для обозначения пропущенных данных. Поскольку NaN имеют необычную семантику сравнения, они приводят к неожиданному или неопределенному поведению в функциях статистики, которые сортируют данные или подсчитывают вхождения. Затронутые функции: median(), median_low(), median_high(), median_grouped(), mode(), multimode() и quantiles(). Перед вызовом этих функций значения NaN следует удалить:

>>> from statistics import median
>>> from math import isnan
>>> from itertools import filterfalse

>>> data = [20.7, float('NaN'),19.2, 18.3, float('NaN'), 14.4]
>>> sorted(data)  # Это приводит к неожиданному поведению
[20.7, nan, 14.4, 18.3, 19.2, nan]
>>> median(data)  # Этот результат неожиданный
16.35

>>> sum(map(isnan, data))    # Количество пропущенных значений
2
>>> clean = list(filterfalse(isnan, data))  # Удалить NaN-значения
>>> clean
[20.7, 19.2, 18.3, 14.4]
>>> sorted(clean)  # Сортировка теперь работает как ожидается
[14.4, 18.3, 19.2, 20.7]
>>> median(clean)       # Этот результат теперь определён корректно
18.75

Средние значения и меры центрального положенияAverages and measures of central location

Эти функции вычисляют среднее или типичное значение из генеральной совокупности или выборки.

mean()

Среднее арифметическое (среднее) данных.

fmean()

Быстрое среднее арифметическое с плавающей запятой, с возможностью взвешивания.

geometric_mean()

Среднее геометрическое данных.

harmonic_mean()

Среднее гармоническое данных.

median()

Медиана (среднее значение) данных.

median_low()

Нижняя медиана данных.

median_high()

Верхняя медиана данных.

median_grouped()

Медиана (50-й процентиль) сгруппированных данных.

mode()

Единственная мода (наиболее часто встречающееся значение) дискретных или номинальных данных.

multimode()

Список мод (наиболее часто встречающихся значений) дискретных или номинальных данных.

quantiles()

Разделение данных на интервалы с равной вероятностью.

Меры разбросаMeasures of spread

Эти функции вычисляют меру того, насколько генеральная совокупность или выборка склонны отклоняться от типичных или средних значений.

pstdev()

Стандартное отклонение генеральной совокупности данных.

pvariance()

Дисперсия генеральной совокупности данных.

stdev()

Стандартное отклонение выборки данных.

variance()

Дисперсия выборки данных.

Статистика взаимосвязей между двумя входными даннымиStatistics for relations between two inputs

Эти функции вычисляют статистики, касающиеся взаимосвязей между двумя наборами данных.

covariance()

Выборочная ковариация двух переменных.

correlation()

Коэффициенты корреляции Пирсона и Спирмена.

linear_regression()

Наклон и пересечение для простой линейной регрессии.

Подробности функцииFunction details

Примечание: функции не требуют, чтобы переданные им данные были отсортированы. Однако для удобства чтения в большинстве примеров показаны отсортированные последовательности.

statistics.mean(data)

Возвращает выборочное среднее арифметическое data, который может быть последовательностью или итерируемым объектом.

Среднее арифметическое – это сумма данных, делённая на количество точек данных. Его часто называют «средним значением», хотя это лишь одна из многих различных математических средних. Это мера центрального положения данных.

Если data пуст, будет возбуждено StatisticsError.

Некоторые примеры использования:

>>> mean([1, 2, 3, 4, 4])
2.8
>>> mean([-1.0, 2.5, 3.25, 5.75])
2.625

>>> from fractions import Fraction as F
>>> mean([F(3, 7), F(1, 21), F(5, 3), F(1, 3)])
Fraction(13, 21)

>>> from decimal import Decimal as D
>>> mean([D("0.5"), D("0.75"), D("0.625"), D("0.375")])
Decimal('0.5625')

Примечание

Среднее сильно подвержено влиянию выбросов и не обязательно является типичным примером точек данных. Для более устойчивой, хотя и менее эффективной, меры центральной тенденции см. median().

Выборочное среднее даёт несмещённую оценку истинного среднего генеральной совокупности, так что при усреднении по всем возможным выборкам mean(sample) сходится к истинному среднему всей совокупности. Если data представляет всю совокупность, а не выборку, то mean(data) эквивалентно вычислению истинного среднего генеральной совокупности μ.

statistics.fmean(data, weights=None)

Преобразует data в числа с плавающей запятой и вычисляет среднее арифметическое.

Эта функция работает быстрее, чем mean(), и всегда возвращает float. data может быть последовательностью или итерируемым объектом. Если входной набор данных пуст, возбуждает StatisticsError.

>>> fmean([3.5, 4.0, 5.25])
4.25

Поддерживается необязательное взвешивание. Например, преподаватель выставляет оценку за курс, взвешивая контрольные работы на 20%, домашние задания на 20%, промежуточный экзамен на 30% и итоговый экзамен на 30%:

>>> grades = [85, 92, 83, 91]
>>> weights = [0.20, 0.20, 0.30, 0.30]
>>> fmean(grades, weights)
87.6

Если указаны weights, их длина должна совпадать с длиной data, иначе будет возбуждено ValueError.

Добавлено в версии 3.8.

Изменено в версии 3.11: Добавлена поддержка weights.

statistics.geometric_mean(data)

Преобразует data в числа с плавающей запятой и вычисляет среднее геометрическое.

Среднее геометрическое указывает центральную тенденцию или типичное значение data, используя произведение значений (в отличие от среднего арифметического, которое использует их сумму).

Возбуждает StatisticsError, если входной набор данных пуст, содержит ноль или отрицательное значение. data может быть последовательностью или итерируемым объектом.

Не предпринимается особых усилий для достижения точных результатов. (Однако в будущем это может измениться.)

>>> round(geometric_mean([54, 24, 36]), 1)
36.0

Добавлено в версии 3.8.

statistics.harmonic_mean(data, weights=None)

Возвращает среднее гармоническое data, последовательности или итерируемого объекта вещественных чисел. Если weights опущен или None, то предполагается равное взвешивание.

Среднее гармоническое – это обратная величина среднего арифметического mean() обратных величин данных. Например, среднее гармоническое трёх значений a, b и c будет эквивалентно 3/(1/a + 1/b + 1/c). Если одно из значений равно нулю, результат будет равен нулю.

Среднее гармоническое – это разновидность среднего, мера центрального положения данных. Его часто применяют при усреднении отношений или скоростей, например, скоростей.

Предположим, автомобиль проезжает 10 км со скоростью 40 км/ч, а затем ещё 10 км со скоростью 60 км/ч. Какова средняя скорость?

>>> harmonic_mean([40, 60])
48.0

Предположим, автомобиль движется со скоростью 40 км/ч в течение 5 км, а когда трасса освобождается, ускоряется до 60 км/ч на оставшихся 30 км пути. Какова средняя скорость?

>>> harmonic_mean([40, 60], weights=[5, 30])
56.0

StatisticsError возбуждается, если data пуст, любой элемент меньше нуля или если взвешенная сумма не является положительной.

Текущий алгоритм выполняет досрочный выход при обнаружении нуля во входных данных. Это означает, что последующие входные данные не проверяются на корректность. (Такое поведение может измениться в будущем.)

Добавлено в версии 3.6.

Изменено в версии 3.10: Добавлена поддержка weights.

statistics.median(data)

Возвращает медиану (среднее значение) числовых данных, используя стандартный метод «среднее двух средних». Если data пусто, вызывается StatisticsError. data может быть последовательностью или итератором.

Медиана – это устойчивая мера центральной тенденции, менее подверженная влиянию выбросов. Если количество точек данных нечётное, возвращается средняя точка:

>>> median([1, 3, 5])
3

Если количество точек данных чётное, медиана интерполируется как среднее двух средних значений:

>>> median([1, 3, 5, 7])
4.0

Это подходит для дискретных данных, когда допустимо, что медиана может не быть фактической точкой данных.

Если данные порядковые (поддерживают операции сравнения), но не числовые (не поддерживают сложение), рассмотрите возможность использования median_low() или median_high() вместо этого.

statistics.median_low(data)

Возвращает нижнюю медиану числовых данных. Если data пусто, вызывается StatisticsError. data может быть последовательностью или итератором.

Нижняя медиана всегда является элементом набора данных. При нечётном количестве точек возвращается среднее значение. При чётном – возвращается меньшее из двух средних значений.

>>> median_low([1, 3, 5])
3
>>> median_low([1, 3, 5, 7])
3

Используйте нижнюю медиану, когда данные дискретны и вы предпочитаете, чтобы медиана была фактической точкой данных, а не интерполированной.

statistics.median_high(data)

Возвращает верхнюю медиану данных. Если data пусто, вызывается StatisticsError. data может быть последовательностью или итератором.

Верхняя медиана всегда является элементом набора данных. При нечётном количестве точек возвращается среднее значение. При чётном – возвращается большее из двух средних значений.

>>> median_high([1, 3, 5])
3
>>> median_high([1, 3, 5, 7])
5

Используйте верхнюю медиану, когда данные дискретны и вы предпочитаете, чтобы медиана была фактической точкой данных, а не интерполированной.

statistics.median_grouped(data, interval=1.0)

Оценивает медиану для числовых данных, сгруппированных или разбитых на интервалы вокруг середин последовательных интервалов фиксированной ширины.

data может быть любым итератором числовых данных, где каждое значение является в точности серединой интервала. Должно присутствовать хотя бы одно значение.

interval – это ширина каждого интервала.

Например, демографические данные могут быть сведены в последовательные десятилетние возрастные группы, каждая из которых представлена пятилетними средними точками интервалов:

>>> from collections import Counter
>>> demographics = Counter({
...    25: 172,   # От 20 до 30 лет
...    35: 484,   # От 30 до 40 лет
...    45: 387,   # От 40 до 50 лет
...    55:  22,   # От 50 до 60 лет
...    65:   6,   # От 60 до 70 лет
... })
...

50-й процентиль (медиана) – это 536-й человек из когорты из 1071 участника. Этот человек находится в возрастной группе от 30 до 40 лет.

Обычная функция median() предполагала бы, что всем в возрастной группе 30–40 лет ровно 35 лет. Более обоснованное предположение – что 484 члена этой группы равномерно распределены между 30 и 40. Для этого используется median_grouped():

>>> data = list(demographics.elements())
>>> median(data)
35
>>> round(median_grouped(data, interval=10), 1)
37.5

Вызывающий код отвечает за то, чтобы точки данных были разделены точными кратными интервала. Это необходимо для получения правильного результата. Функция не проверяет это предусловие.

Входные данные могут быть любым числовым типом, который можно привести к float на этапе интерполяции.

statistics.mode(data)

Возвращает единственное наиболее часто встречающееся значение из дискретных или номинальных данных. Мода (когда существует) – это наиболее типичное значение и служит мерой центрального положения.

Если есть несколько мод с одинаковой частотой, возвращается первая, встреченная в данных. Если требуется наименьшая или наибольшая из них, используйте min(multimode(data)) или max(multimode(data)). Если входные данные пусты, возбуждается StatisticsError.

mode предполагает дискретные данные и возвращает одно значение. Это стандартный подход к моде, как обычно учат в школах:

>>> mode([1, 1, 2, 3, 3, 3, 3, 4])
3

Мода уникальна тем, что это единственная статистика в этом пакете, которая также применима к номинальным (нечисловым) данным:

>>> mode(["red", "blue", "blue", "red", "green", "red", "red"])
'red'

Поддерживаются только хешируемые входные данные. Для обработки типа set рассмотрите приведение к frozenset. Для обработки типа list рассмотрите приведение к tuple. Для смешанных или вложенных входных данных рассмотрите использование этого более медленного квадратичного алгоритма, который зависит только от проверок на равенство: max(data, key=data.count).

Изменено в версии 3.8: Теперь обрабатывает мультимодальные наборы данных, возвращая первую встреченную моду. Ранее возбуждалось StatisticsError, когда находилось более одной моды.

statistics.multimode(data)

Возвращает список наиболее часто встречающихся значений в порядке их первого появления в данных. Вернёт более одного результата, если есть несколько мод, или пустой список, если данные пусты:

>>> multimode('aabbbbccddddeeffffgg')
['b', 'd', 'f']
>>> multimode('')
[]

Добавлено в версии 3.8.

statistics.pstdev(data, mu=None)

Возвращает стандартное отклонение генеральной совокупности (квадратный корень из дисперсии генеральной совокупности). См. pvariance() для получения аргументов и других подробностей.

>>> pstdev([1.5, 2.5, 2.5, 2.75, 3.25, 4.75])
0.986893273527251
statistics.pvariance(data, mu=None)

Возвращает дисперсию генеральной совокупности для данных – непустой последовательности или итерации вещественных чисел. Дисперсия (второй центральный момент) – это мера изменчивости (разброса или рассеяния) данных. Большая дисперсия указывает на то, что данные разбросаны; малая – что они сгруппированы близко к среднему.

Если указан необязательный второй аргумент mu, он должен быть средним генеральной совокупности для данных. Его также можно использовать для вычисления второго момента относительно точки, не являющейся средним. Если он отсутствует или равен None (по умолчанию), среднее арифметическое вычисляется автоматически.

Используйте эту функцию для расчёта дисперсии по всей генеральной совокупности. Для оценки дисперсии по выборке обычно лучше подходит функция variance().

Возбуждает StatisticsError, если данные пусты.

Примеры:

>>> data = [0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25]
>>> pvariance(data)
1.25

Если вы уже вычислили среднее своих данных, вы можете передать его в качестве необязательного второго аргумента mu, чтобы избежать повторного вычисления:

>>> mu = mean(data)
>>> pvariance(data, mu)
1.25

Поддерживаются типы Decimal и Fraction:

>>> from decimal import Decimal as D
>>> pvariance([D("27.5"), D("30.25"), D("30.25"), D("34.5"), D("41.75")])
Decimal('24.815')

>>> from fractions import Fraction as F
>>> pvariance([F(1, 4), F(5, 4), F(1, 2)])
Fraction(13, 72)

Примечание

При вызове для всей генеральной совокупности получается дисперсия генеральной совокупности σ². При вызове для выборки получается смещённая выборочная дисперсия s², также известная как дисперсия с N степенями свободы.

Если вам каким-либо образом известно истинное среднее генеральной совокупности μ, вы можете использовать эту функцию для расчёта дисперсии выборки, передав известное среднее генеральной совокупности в качестве второго аргумента. При условии, что точки данных являются случайной выборкой из совокупности, результат будет несмещённой оценкой дисперсии генеральной совокупности.

statistics.stdev(data, xbar=None)

Возвращает выборочное стандартное отклонение (квадратный корень из выборочной дисперсии). См. variance() для получения аргументов и других подробностей.

>>> stdev([1.5, 2.5, 2.5, 2.75, 3.25, 4.75])
1.0810874155219827
statistics.variance(data, xbar=None)

Возвращает выборочную дисперсию для данных – итерации, содержащей не менее двух вещественных чисел. Дисперсия (второй центральный момент) – это мера изменчивости (разброса или рассеяния) данных. Большая дисперсия указывает на то, что данные разбросаны; малая – что они сгруппированы близко к среднему.

Если указан необязательный второй аргумент xbar, он должен быть выборочным средним для данных. Если он отсутствует или равен None (по умолчанию), среднее вычисляется автоматически.

Используйте эту функцию, когда ваши данные являются выборкой из генеральной совокупности. Для расчёта дисперсии по всей совокупности см. pvariance().

Возбуждает StatisticsError, если в данных меньше двух значений.

Примеры:

>>> data = [2.75, 1.75, 1.25, 0.25, 0.5, 1.25, 3.5]
>>> variance(data)
1.3720238095238095

Если выборочное среднее данных уже вычислено, его можно передать в качестве необязательного второго аргумента xbar, чтобы избежать повторного вычисления:

>>> m = mean(data)
>>> variance(data, m)
1.3720238095238095

Эта функция не проверяет, было ли передано истинное среднее в качестве xbar. Использование произвольных значений для xbar может привести к неверным или невозможным результатам.

Поддерживаются значения Decimal и Fraction:

>>> from decimal import Decimal as D
>>> variance([D("27.5"), D("30.25"), D("30.25"), D("34.5"), D("41.75")])
Decimal('31.01875')

>>> from fractions import Fraction as F
>>> variance([F(1, 6), F(1, 2), F(5, 3)])
Fraction(67, 108)

Примечание

Это выборочная дисперсия s² с поправкой Бесселя, также известная как дисперсия с N-1 степенями свободы. При условии, что точки данных репрезентативны (например, независимы и одинаково распределены), результат должен быть несмещенной оценкой истинной дисперсии генеральной совокупности.

Если каким-либо образом известно истинное среднее генеральной совокупности μ, его следует передать в функцию pvariance() в качестве параметра mu, чтобы получить дисперсию выборки.

statistics.quantiles(data, *, n=4, method='exclusive')

Разделяет data на n непрерывных интервалов равной вероятности. Возвращает список из n - 1 точек разделения, отделяющих интервалы.

Задайте n равным 4 для квартилей (по умолчанию). Задайте n равным 10 для децилей. Задайте n равным 100 для процентилей, что даёт 99 точек разделения, которые делят data на 100 групп одинакового размера. Возбуждается StatisticsError, если n меньше 1.

data – любой итерируемый объект, содержащий выборочные данные. Для получения осмысленных результатов количество точек данных в data должно быть больше n. Возбуждает StatisticsError, если имеется менее двух точек данных.

Точки разделения линейно интерполируются между двумя ближайшими точками данных. Например, если точка разделения находится на расстоянии одной трети между двумя выборочными значениями, 100 и 112, точка разделения будет равна 104.

Метод method вычисления квантилей может изменяться в зависимости от того, включает ли data наименьшие и наибольшие возможные значения из генеральной совокупности или исключает их.

Метод method по умолчанию – «exclusive», и используется для данных, взятых из генеральной совокупности, которая может содержать более экстремальные значения, чем в выборке. Доля совокупности, попадающая ниже i-го из m отсортированных точек данных, вычисляется как i / (m + 1). Для девяти выборочных значений метод сортирует их и присваивает следующие процентили: 10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%, 90%.

Установка method в «inclusive» используется для описания данных генеральной совокупности или для выборок, которые, как известно, содержат наиболее экстремальные значения из совокупности. Минимальное значение в data рассматривается как 0-й процентиль, а максимальное – как 100-й процентиль. Доля совокупности, попадающая ниже i-го из m отсортированных точек данных, вычисляется как (i - 1) / (m - 1). Для 11 выборочных значений метод сортирует их и присваивает следующие процентили: 0%, 10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%, 90%, 100%.

# Decile cut points for empirically sampled data
>>> data = [105, 129, 87, 86, 111, 111, 89, 81, 108, 92, 110,
...         100, 75, 105, 103, 109, 76, 119, 99, 91, 103, 129,
...         106, 101, 84, 111, 74, 87, 86, 103, 103, 106, 86,
...         111, 75, 87, 102, 121, 111, 88, 89, 101, 106, 95,
...         103, 107, 101, 81, 109, 104]
>>> [round(q, 1) for q in quantiles(data, n=10)]
[81.0, 86.2, 89.0, 99.4, 102.5, 103.6, 106.0, 109.8, 111.0]

Добавлено в версии 3.8.

statistics.covariance(x, y, /)

Возвращает выборочную ковариацию двух входных последовательностей x и y. Ковариация – это мера совместной изменчивости двух входов.

Оба входных параметра должны быть одной длины (не менее двух), в противном случае возбуждается StatisticsError.

Примеры:

>>> x = [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> y = [1, 2, 3, 1, 2, 3, 1, 2, 3]
>>> covariance(x, y)
0.75
>>> z = [9, 8, 7, 6, 5, 4, 3, 2, 1]
>>> covariance(x, z)
-7.5
>>> covariance(z, x)
-7.5

Добавлено в версии 3.10.

statistics.correlation(x, y, /, *, method='linear')

Возвращает коэффициент корреляции Пирсона для двух входных последовательностей. Коэффициент корреляции Пирсона r принимает значения от -1 до +1. Он измеряет силу и направление линейной зависимости.

Если method равен «ranked», вычисляется ранговый коэффициент корреляции Спирмена для двух входов. Данные заменяются рангами. Связи усредняются, чтобы одинаковые значения получали одинаковый ранг. Полученный коэффициент измеряет силу монотонной зависимости.

Коэффициент корреляции Спирмена подходит для порядковых данных или для непрерывных данных, которые не удовлетворяют требованию линейной пропорциональности для коэффициента корреляции Пирсона.

Оба входных параметра должны быть одной длины (не менее двух) и не должны быть константными, иначе возбуждается StatisticsError.

Пример с законами Кеплера движения планет:

>>> # Меркурий, Венера, Земля, Марс, Юпитер, Сатурн, Уран и Нептун
>>> orbital_period = [88, 225, 365, 687, 4331, 10_756, 30_687, 60_190]    # дни
>>> dist_from_sun = [58, 108, 150, 228, 778, 1_400, 2_900, 4_500] # млн км

>>> # Показывает, что существует идеальная монотонная зависимость
>>> correlation(orbital_period, dist_from_sun, method='ranked')
1.0

>>> # Заметим, что линейная связь несовершенна
>>> round(correlation(orbital_period, dist_from_sun), 4)
0.9882

>>> # Демонстрация третьего закона Кеплера: существует линейная корреляция
>>> # между квадратом орбитального периода и кубом
>>> # расстояние от Солнца.
>>> period_squared = [p * p for p in orbital_period]
>>> dist_cubed = [d * d * d for d in dist_from_sun]
>>> round(correlation(period_squared, dist_cubed), 4)
1.0

Добавлено в версии 3.10.

Изменено в версии 3.12: Добавлена поддержка рангового коэффициента корреляции Спирмена.

statistics.linear_regression(x, y, /, *, proportional=False)

Возвращает угловой коэффициент и свободный член простой линейной регрессии, оцененные методом наименьших квадратов. Простая линейная регрессия описывает связь между независимой переменной x и зависимой переменной y с помощью следующей линейной функции:

y = slope * x + intercept + noise

где slope и intercept – оцениваемые параметры регрессии, а noise представляет изменчивость данных, не объяснённую линейной регрессией (она равна разности между предсказанными и фактическими значениями зависимой переменной).

Оба входных параметра должны быть одной длины (не менее двух), а независимая переменная x не может быть константой; в противном случае возбуждается StatisticsError.

Например, можно использовать даты выхода фильмов Монти Пайтона, чтобы предсказать общее количество фильмов Монти Пайтона, которые были бы сняты к 2019 году, если бы темп сохранялся.

>>> year = [1971, 1975, 1979, 1982, 1983]
>>> films_total = [1, 2, 3, 4, 5]
>>> slope, intercept = linear_regression(year, films_total)
>>> round(slope * 2019 + intercept)
16

Если proportional равен true, предполагается, что независимая переменная x и зависимая переменная y прямо пропорциональны. Данные аппроксимируются прямой, проходящей через начало координат. Поскольку intercept всегда будет равен 0.0, базовая линейная функция упрощается до:

y = slope * x + noise

Продолжая пример из correlation(), рассмотрим, насколько хорошо модель, основанная на крупных планетах, может предсказать орбитальные расстояния для карликовых планет:

>>> model = linear_regression(period_squared, dist_cubed, proportional=True)
>>> slope = model.slope

>>> # Карликовые планеты:   Плутон,  Эрида,    Макемаке, Хаумеа, Церера
>>> orbital_periods = [90_560, 204_199, 111_845, 103_410, 1_680]  # дни
>>> predicted_dist = [math.cbrt(slope * (p * p)) for p in orbital_periods]
>>> list(map(round, predicted_dist))
[5912, 10166, 6806, 6459, 414]

>>> [5_906, 10_152, 6_796, 6_450, 414]  # фактическое расстояние в миллионах км
[5906, 10152, 6796, 6450, 414]

Добавлено в версии 3.10.

Изменено в версии 3.11: Добавлена поддержка для пропорционального.

ИсключенияExceptions

Определено одно исключение:

exception statistics.StatisticsError

Подкласс ValueError для исключений, связанных со статистикой.

NormalDist объектыNormalDist objects

NormalDist – это инструмент для создания и работы с нормальными распределениями случайной величины. Это класс, который рассматривает среднее и стандартное отклонение измерений данных как единую сущность.

Нормальные распределения возникают из Центральной предельной теоремы и имеют широкий спектр применений в статистике.

class statistics.NormalDist(mu=0.0, sigma=1.0)

Возвращает новый объект NormalDist, где mu представляет среднее арифметическое, а sigma представляет стандартное отклонение.

Если sigma отрицательно, возбуждает StatisticsError.

mean

Свойство только для чтения для среднего арифметического нормального распределения.

median

Свойство только для чтения для медианы нормального распределения.

mode

Свойство только для чтения для моды нормального распределения.

stdev

Свойство только для чтения для стандартного отклонения нормального распределения.

variance

Свойство только для чтения для дисперсии нормального распределения. Равна квадрату стандартного отклонения.

classmethod from_samples(data)

Создаёт экземпляр нормального распределения с параметрами mu и sigma, оценёнными по data с использованием fmean() и stdev().

data может быть любой итерируемой последовательностью и должна состоять из значений, которые можно преобразовать в тип float. Если data не содержит хотя бы два элемента, возбуждается StatisticsError, поскольку для оценки центрального значения требуется хотя бы одна точка, а для оценки разброса – хотя бы две.

samples(n, *, seed=None)

Генерирует n случайных выборок для заданных среднего и стандартного отклонения. Возвращает list из float значений.

Если указан seed, создаётся новый экземпляр базового генератора случайных чисел. Это полезно для получения воспроизводимых результатов, даже в контексте многопоточности.

pdf(x)

Используя функцию плотности вероятности (pdf), вычисляет относительную вероятность того, что случайная величина X будет около заданного значения x. Математически это предел отношения P(x <= X < x+dx) / dx при dx, стремящемся к нулю.

Относительная вероятность вычисляется как вероятность попадания выборки в узкий диапазон, делённая на ширину диапазона (отсюда слово «плотность»). Поскольку вероятность относительна по отношению к другим точкам, её значение может быть больше 1.0.

cdf(x)

Используя функцию кумулятивного распределения (cdf), вычислить вероятность того, что случайная величина X будет меньше или равна x. Математически это записывается как P(X <= x).

inv_cdf(p)

Вычисляет обратную функцию кумулятивного распределения, также известную как квантильная функция или процентная точка. Математически это записывается как x : P(X <= x) = p.

Находит значение x случайной величины X, такое что вероятность того, что переменная будет меньше или равна этому значению, равна заданной вероятности p.

overlap(other)

Измеряет согласие между двумя нормальными распределениями вероятностей. Возвращает значение от 0.0 до 1.0, представляющее площадь перекрытия для двух функций плотности вероятности.

quantiles(n=4)

Делит нормальное распределение на n непрерывных интервалов с равной вероятностью. Возвращает список из (n - 1) точек разделения, отделяющих интервалы.

Установите n равным 4 для квартилей (по умолчанию). Установите n равным 10 для децилей. Установите n равным 100 для процентилей, что дает 99 точек разделения, которые делят нормальное распределение на 100 групп равного размера.

zscore(x)

Вычисляет стандартный балл описывающий x через количество стандартных отклонений выше или ниже среднего нормального распределения: (x - mean) / stdev.

Добавлено в версии 3.9.

Экземпляры NormalDist поддерживают сложение, вычитание, умножение и деление на константу. Эти операции используются для смещения и масштабирования. Например:

>>> temperature_february = NormalDist(5, 2.5)             # Цельсий
>>> temperature_february * (9/5) + 32                     # Фаренгейт
NormalDist(mu=41.0, sigma=4.5)

Деление константы на экземпляр NormalDist не поддерживается, поскольку результат не был бы нормально распределен.

Поскольку нормальные распределения возникают из аддитивных эффектов независимых переменных, можно складывать и вычитать две независимые нормально распределенные случайные величины, представленные в виде экземпляров NormalDist. Например:

>>> birth_weights = NormalDist.from_samples([2.5, 3.1, 2.1, 2.4, 2.7, 3.5])
>>> drug_effects = NormalDist(0.4, 0.15)
>>> combined = birth_weights + drug_effects
>>> round(combined.mean, 1)
3.1
>>> round(combined.stdev, 1)
0.5

Добавлено в версии 3.8.

Примеры и рецептыExamples and Recipes

Классические задачи теории вероятностейClassic probability problems

NormalDist легко решает классические задачи теории вероятностей.

Например, имея исторические данные по экзаменам SAT, показывающие, что баллы распределены нормально со средним 1060 и стандартным отклонением 195, определите процент студентов с баллами между 1100 и 1200, округлив до ближайшего целого числа:

>>> sat = NormalDist(1060, 195)
>>> fraction = sat.cdf(1200 + 0.5) - sat.cdf(1100 - 0.5)
>>> round(fraction * 100.0, 1)
18.4

Найдите квартили и децили для баллов SAT:

>>> list(map(round, sat.quantiles()))
[928, 1060, 1192]
>>> list(map(round, sat.quantiles(n=10)))
[810, 896, 958, 1011, 1060, 1109, 1162, 1224, 1310]

Входные данные Монте-Карло для симуляцийMonte Carlo inputs for simulations

Чтобы оценить распределение для модели, которую сложно решить аналитически, NormalDist может генерировать входные выборки для симуляции Монте-Карло:

>>> def model(x, y, z):
...     return (3*x + 7*x*y - 5*y) / (11 * z)
...
>>> n = 100_000
>>> X = NormalDist(10, 2.5).samples(n, seed=3652260728)
>>> Y = NormalDist(15, 1.75).samples(n, seed=4582495471)
>>> Z = NormalDist(50, 1.25).samples(n, seed=6582483453)
>>> quantiles(map(model, X, Y, Z))
[1.4591308524824727, 1.8035946855390597, 2.175091447274739]

Аппроксимация биномиальных распределенийApproximating binomial distributions

Нормальные распределения можно использовать для аппроксимации биномиальных распределений, когда размер выборки велик и вероятность успешного испытания близка к 50%.

Например, на конференции с открытым исходным кодом 750 участников и два зала вместимостью 500 человек каждый. Есть доклад о Python и другой о Ruby. На предыдущих конференциях 65% участников предпочитали слушать доклады о Python. Предполагая, что предпочтения аудитории не изменились, какова вероятность того, что зал для Python не превысит свою вместимость?

>>> n = 750             # Размер выборки
>>> p = 0.65            # Предпочтение Python
>>> q = 1.0 - p         # Предпочтение Ruby
>>> k = 500             # Вместимость комнаты

>>> # Аппроксимация с помощью кумулятивного нормального распределения
>>> from math import sqrt
>>> round(NormalDist(mu=n*p, sigma=sqrt(n*p*q)).cdf(k + 0.5), 4)
0.8402

>>> # Точное решение с помощью кумулятивного биномиального распределения
>>> from math import comb, fsum
>>> round(fsum(comb(n, r) * p**r * q**(n-r) for r in range(k+1)), 4)
0.8402

>>> # Аппроксимация с помощью симуляции
>>> from random import seed, binomialvariate
>>> seed(8675309)
>>> mean(binomialvariate(n, p) <= k for i in range(10_000))
0.8406

Наивный байесовский классификаторNaive bayesian classifier

Нормальные распределения часто встречаются в задачах машинного обучения.

В Wikipedia есть хороший пример наивного байесовского классификатора. Задача – предсказать пол человека по измерениям нормально распределенных признаков, включая рост, вес и размер ноги.

Дан обучающий набор данных с измерениями для восьми человек. Предполагается, что измерения нормально распределены, поэтому мы обобщаем данные с помощью NormalDist:

>>> height_male = NormalDist.from_samples([6, 5.92, 5.58, 5.92])
>>> height_female = NormalDist.from_samples([5, 5.5, 5.42, 5.75])
>>> weight_male = NormalDist.from_samples([180, 190, 170, 165])
>>> weight_female = NormalDist.from_samples([100, 150, 130, 150])
>>> foot_size_male = NormalDist.from_samples([12, 11, 12, 10])
>>> foot_size_female = NormalDist.from_samples([6, 8, 7, 9])

Далее мы встречаем нового человека, чьи измерения признаков известны, но чей пол неизвестен:

>>> ht = 6.0        # рост
>>> wt = 130        # вес
>>> fs = 8          # размер ноги

Начиная с 50% априорной вероятности быть мужчиной или женщиной, мы вычисляем апостериорную как априорную, умноженную на произведение правдоподобий для измерений признаков при данном поле:

>>> prior_male = 0.5
>>> prior_female = 0.5
>>> posterior_male = (prior_male * height_male.pdf(ht) *
...                   weight_male.pdf(wt) * foot_size_male.pdf(fs))

>>> posterior_female = (prior_female * height_female.pdf(ht) *
...                     weight_female.pdf(wt) * foot_size_female.pdf(fs))

Окончательный прогноз отдается наибольшей апостериорной вероятности. Это известно как максимум апостериорной вероятности или MAP:

>>> 'male' if posterior_male > posterior_female else 'female'
'female'

Оценка плотности ядраKernel density estimation

Можно оценить непрерывное распределение вероятностей по фиксированному числу дискретных выборок.

Основная идея – сгладить данные с помощью ядерной функции, такой как нормальное, треугольное или равномерное распределение. Степень сглаживания регулируется параметром масштаба, h, который называется шириной окна.

from random import choice, random

def kde_normal(data, h):
    "Create a continuous probability distribution from discrete samples."

    # Сглаживает данные с помощью ядра нормального распределения, масштабированного на h.
    K_h = NormalDist(0.0, h)

    def pdf(x):
        'Probability density function.  P(x <= X < x+dx) / dx'
        return sum(K_h.pdf(x - x_i) for x_i in data) / len(data)

    def cdf(x):
        'Cumulative distribution function.  P(X <= x)'
        return sum(K_h.cdf(x - x_i) for x_i in data) / len(data)

    def rand():
        'Random selection from the probability distribution.'
        return choice(data) + K_h.inv_cdf(random())

    return pdf, cdf, rand

На Википедии есть пример, где можно использовать рецепт kde_normal() для генерации и построения функции плотности вероятности, оценённой по небольшой выборке:

>>> sample = [-2.1, -1.3, -0.4, 1.9, 5.1, 6.2]
>>> pdf, cdf, rand = kde_normal(sample, h=1.5)
>>> xarr = [i/100 for i in range(-750, 1100)]
>>> yarr = [pdf(x) for x in xarr]

Точки из xarr и yarr можно использовать для построения графика PDF:

Точечная диаграмма оценки функции плотности вероятности.

Перевыборка данных для получения 100 новых выборок:

>>> new_selections = [rand() for i in range(100)]

Определите вероятность того, что новое значение окажется ниже 2.0:

>>> round(cdf(2.0), 4)
0.5794

Добавьте новую точку данных и найдите новую ФРП в 2.0:

>>> sample.append(4.9)
>>> round(cdf(2.0), 4)
0.5005