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

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


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

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

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

Средние и измерения центрального расположения

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

mean() Среднее арифметическое («среднее») данных.
fmean() Быстрое арифметическое с плавающей точкой.
geometric_mean() Среднее геометрическое данных.
harmonic_mean() Гармоническое среднее данных.
median() Медиана (среднее значение) данных.
median_low() Низкая медиана данных.
median_high() Высокая медиана данных.
median_grouped() Медиана или 50й процентиль сгруппированных данных.
mode() Одиночный режим (наиболее распространенное значение) дискретных или номинальных данных.
multimode() Список режимов (наиболее распространенных значений) дискретных или номинальных данных.
quantiles() Разделение данных на интервалы с равной вероятностью.

Меры распространения

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

pstdev() Популяционное стандартное отклонение данных.
pvariance() Популяционная дисперсия данных.
stdev() Стандартное отклонение выборки данных.
variance() Выборочная дисперсия данных.

Подробнее про функции

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

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() и mode().

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

statistics.fmean(data)

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

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

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

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

statistics.geometric_mean(data)

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

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

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

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

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

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

statistics.harmonic_mean(data)

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

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

Гармоническое среднее — это тип среднего, мера центрального расположения данных. Это часто уместно при усреднении показателей или соотношений, например скоростей.

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

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

Предположим, инвестор покупает акции каждой из трёх компаний равной стоимости с коэффициентами P/E (цена/прибыль) 2.5, 3 и 10. Каков средний коэффициент P/E для портфеля инвестора?

>>> harmonic_mean([2.5, 3, 10])  # Для равного инвестиционного портфеля.
3.6

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

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

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

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)

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

>>> median_grouped([52, 52, 53, 54])
52.5

В следующем примере данные округлены, так что каждое значение представляет собой среднюю точку классов данных, например 1 — это средняя точка класса 0.5–1.5, 2 — средняя точка 1.5–2.5, 3 — средняя точка 2.5–3.5 и т. д. При приведённых данных среднее значение попадает где-то в класс 3.5–4.5, и для его оценки используется интерполяция:

>>> median_grouped([1, 2, 2, 3, 4, 4, 4, 4, 4, 5])
3.7

Необязательный аргумент interval представляет интервал класса и по умолчанию равен 1. При изменении интервала класса естественным образом изменяется интерполяция:

>>> median_grouped([1, 3, 3, 5, 7], interval=1)
3.25
>>> median_grouped([1, 3, 3, 5, 7], interval=2)
3.5

Функция не проверяет, разнесены ли точки данных как минимум на interval.

Детали реализации CPython: При некоторых обстоятельствах median_grouped() может преобразовывать точки данных в плавающие. Это поведение, вероятно, изменится в будущем.

См.также

  • «Статистика поведенческих наук», Фредерик Дж. Граветтер и Ларри Б. Валлнау (8-е издание).
  • Функция SSMEDIAN в электронной таблице Gnome Gnumeric, включая это обсуждение.
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'

Изменено в версии 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().

Вызывает StatisticsError, если data пуст.

Примеры:

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

Повышает StatisticsError, если у data менее двух значений.

Примеры:

>>> 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 может привести к недействительным или невозможным результатам.

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

>>> 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-th из m отсортированных точек данных, вычисляется как i / (m + 1). Учитывая девять значений выборки, метод сортирует их и назначает следующие процентили: 10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%, 90%.

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

# Децильные точки для эмпирически выбранных данных
>>> 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.

Исключения

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

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 групп равного размера.

Экземпляры 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.

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

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             # Размер образца
>>> 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, choices
>>> seed(8675309)
>>> def trial():
...     return choices(('Python', 'Ruby'), (p, q), k=n).count('Python')
>>> mean(trial() <= k for i in range(10_000))
0.8398

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

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

Нам дано множество тренировочных данных с измерениями для восьми человек. Предполагается, что измерения имеют нормальное распределение, поэтому мы суммируем данные с 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'