Spec-Zone.ru › Python 3.12

statistics — Функции математической статистики

Добавлено в версии 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)  # This has surprising behavior
[20.7, nan, 14.4, 18.3, 19.2, nan]
>>> median(data)  # This result is unexpected
16.35

>>> sum(map(isnan, data))    # Number of missing values
2
>>> clean = list(filterfalse(isnan, data))  # Strip NaN values
>>> clean
[20.7, 19.2, 18.3, 14.4]
>>> sorted(clean)  # Sorting now works as expected
[14.4, 18.3, 19.2, 20.7]
>>> median(clean)       # This result is now well defined
18.75

Средние значения и меры центральной тенденции

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

mean()

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

fmean()

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

geometric_mean()

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

harmonic_mean()

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

median()

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

median_low()

Меньшая медиана данных.

median_high()

Большая медиана данных.

median_grouped()

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

mode()

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

multimode()

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

quantiles()

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

Меры разброса

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

pstdev()

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

pvariance()

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

stdev()

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

variance()

Дисперсия выборки.

Статистические характеристики взаимосвязей между двумя наборами данных

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

covariance()

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

correlation()

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

linear_regression()

Угловой коэффициент и отрезок, отсекаемый на оси ординат, для простой линейной регрессии.

Описание функций

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

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

Предположим, автомобиль проезжает 5 км со скоростью 40 км/ч, а после того, как движение становится свободным, увеличивает скорость до 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 — это ширина каждого интервала.

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

>>> from collections import Counter
>>> demographics = Counter({
...    25: 172,   # 20 to 30 years old
...    35: 484,   # 30 to 40 years old
...    45: 387,   # 40 to 50 years old
...    55:  22,   # 50 to 60 years old
...    65:   6,   # 60 to 70 years old
... })
...

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

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

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

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

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

statistics.mode(data)

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

Если несколько мод имеют одинаковую частоту, возвращается первая из них, встреченная в data. Если вместо этого требуется наименьшая или наибольшая из них, используйте min(multimode(data)) или max(multimode(data)). Если входные данные 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)

Возвращает список наиболее часто встречающихся значений в порядке их первого появления в data. Если существует несколько мод, возвращается более одного результата; если 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)

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

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

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

Если data пусто, вызывается исключение 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

Поддерживаются десятичные дроби и дроби:

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

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

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

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

Если data содержит меньше двух значений, вызывается исключение 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 равных групп. Если n меньше 1, вызывается исключение StatisticsError.

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

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

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

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

Метод “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.

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

>>> # Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, and  Neptune
>>> orbital_period = [88, 225, 365, 687, 4331, 10_756, 30_687, 60_190]    # days
>>> dist_from_sun = [58, 108, 150, 228, 778, 1_400, 2_900, 4_500] # million km

>>> # Show that a perfect monotonic relationship exists
>>> correlation(orbital_period, dist_from_sun, method='ranked')
1.0

>>> # Observe that a linear relationship is imperfect
>>> round(correlation(orbital_period, dist_from_sun), 4)
0.9882

>>> # Demonstrate Kepler's third law: There is a linear correlation
>>> # between the square of the orbital period and the cube of the
>>> # distance from the sun.
>>> 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

>>> # Dwarf planets:   Pluto,  Eris,    Makemake, Haumea, Ceres
>>> orbital_periods = [90_560, 204_199, 111_845, 103_410, 1_680]  # days
>>> 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]  # actual distance in million km
[5906, 10152, 6796, 6450, 414]

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

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

Исключения

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

exception statistics.StatisticsError

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

Объекты NormalDist

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)             # Celsius
>>> temperature_february * (9/5) + 32                     # Fahrenheit
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.

Примеры и рецепты

Классические задачи на вероятность

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]

Входные данные Монте-Карло для моделирования

Чтобы оценить распределение для модели, которую сложно решить аналитически, 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]

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

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

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

>>> n = 750             # Sample size
>>> p = 0.65            # Preference for Python
>>> q = 1.0 - p         # Preference for Ruby
>>> k = 500             # Room capacity

>>> # Approximation using the cumulative normal distribution
>>> from math import sqrt
>>> round(NormalDist(mu=n*p, sigma=sqrt(n*p*q)).cdf(k + 0.5), 4)
0.8402

>>> # Exact solution using the cumulative binomial distribution
>>> from math import comb, fsum
>>> round(fsum(comb(n, r) * p**r * q**(n-r) for r in range(k+1)), 4)
0.8402

>>> # Approximation using a simulation
>>> from random import seed, binomialvariate
>>> seed(8675309)
>>> mean(binomialvariate(n, p) <= k for i in range(10_000))
0.8406

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

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

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

Нам предоставлен обучающий набор данных с измерениями для восьми человек. Предполагается, что измерения распределены нормально, поэтому мы обобщим данные с помощью 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        # height
>>> wt = 130        # weight
>>> fs = 8          # foot size

Исходя из априорной вероятности 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'

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

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

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

from random import choice, random

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

    # Smooth the data with a normal distribution kernel scaled by 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:

Scatter plot of the estimated probability density function.

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

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

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

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

Добавьте новую точку данных выборки и найдите новое значение CDF при 2.0:

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

© 2001–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.12/library/statistics.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API