scipy.stats.

make_distribution#

scipy.stats.make_distribution(dist)[источник]#

Сгенерировать UnivariateDistribution класс из совместимого объекта

Аргумент может быть экземпляром rv_continuous или экземпляр другого класса, удовлетворяющего интерфейсу, описанному ниже.

Возвращаемое значение представляет собой ContinuousDistribution подкласс, если входные данные являются экземпляром rv_continuous или DiscreteDistribution подкласс, если входной объект является экземпляром rv_discrete. Как и любой подкласс UnivariateDistribution, он должен быть создан (т.е. путём передачи всех параметров формы как ключевых аргументов) перед использованием. После создания результирующий объект будет иметь тот же интерфейс, что и любой другой экземпляр UnivariateDistribution; например, scipy.stats.Normal, scipy.stats.Binomial.

Примечание

make_distribution не работает идеально со всеми экземплярами rv_continuous. Известные сбои включают levy_stable, vonmises, hypergeom, ‘nchypergeom_fisher’, ‘nchypergeom_wallenius’, и poisson_binom. Некоторые методы некоторых распределений не поддерживают параметры формы массива.

Параметры:
distrv_continuous

Экземпляр rv_continuous, rv_discrete, или экземпляр любого класса с следующими атрибутами:

__make_distribution_version__str

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

параметрыdict или tuple

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

конечные точкикортеж, по умолчанию: (-inf, inf)

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

inclusiveкортеж bool, по умолчанию: (False, False)

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

типичныйкортеж, по умолчанию: endpoints

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

Кортежное значение (a, b) связанный с ключом в parameters словарь эквивалентен {endpoints: (a, b)}.

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

поддержкаdict или tuple

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

Класс должен также определяет pdf метод и может определить методы logentropy, entropy, median, mode, logpdf, logcdf, cdf, logccdf, ccdf, ilogcdf, icdf, ilogccdf, iccdf, moment, и sample. Если определены, эти методы должны принимать параметры распределения как ключевые аргументы, а также принимать любые позиционные аргументы, принимаемые соответствующим методом ContinuousDistribution. Когда определено несколько параметризаций, эти методы должны принимать все параметры из всех параметризаций. moment метод должен принимать order и kind аргументы по позиции или ключевому слову, но может возвращать None если формула недоступна для аргументов; в этом случае инфраструктура вернется к реализации по умолчанию. sample метод должен принимать shape по позиции или ключевому слову, но в отличие от публичного метода с тем же именем, аргумент, который он получает, будет полный форма выходного массива - то есть форма, переданная в публичный метод, дополненная к трансляционной форме параметров случайной величины.

Возвращает:
CustomDistributionUnivariateDistribution

Подкласс UnivariateDistribution соответствующий dist. Инициализатор требует передачи всех параметров формы в качестве именованных аргументов (используя те же имена, что и экземпляр rv_continuous/rv_discrete).

Примечания

Документация UnivariateDistribution не отображается. См. ниже пример того, как создать экземпляр класса (т.е. передать все параметры формы dist в инициализатор в качестве ключевых аргументов). Документация всех методов идентична документации scipy.stats.Normal. Используйте help на возвращаемом классе или его методах для получения дополнительной информации.

Примеры

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> from scipy import stats
>>> from scipy import special

Создать ContinuousDistribution из scipy.stats.loguniform.

>>> LogUniform = stats.make_distribution(stats.loguniform)
>>> X = LogUniform(a=1.0, b=3.0)
>>> np.isclose((X + 0.25).median(), stats.loguniform.ppf(0.5, 1, 3, loc=0.25))
np.True_
>>> X.plot()
>>> sample = X.sample(10000, rng=np.random.default_rng())
>>> plt.hist(sample, density=True, bins=30)
>>> plt.legend(('pdf', 'histogram'))
>>> plt.show()
../../_images/scipy-stats-make_distribution-1_00_00.png

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

>>> class MyLogUniform:
...     @property
...     def __make_distribution_version__(self):
...         return "1.16.0"
...
...     @property
...     def parameters(self):
...         return {'a': {'endpoints': (0, np.inf),
...                       'inclusive': (False, False)},
...                 'b': {'endpoints': ('a', np.inf),
...                       'inclusive': (False, False)}}
...
...     @property
...     def support(self):
...         return {'endpoints': ('a', 'b'), 'inclusive': (True, True)}
...
...     def pdf(self, x, a, b):
...         return 1 / (x * (np.log(b)- np.log(a)))
>>>
>>> MyLogUniform = stats.make_distribution(MyLogUniform())
>>> Y = MyLogUniform(a=1.0, b=3.0)
>>> np.isclose(Y.cdf(2.), X.cdf(2.))
np.True_

Создать пользовательское распределение с переменной областью определения.

>>> class MyUniformCube:
...     @property
...     def __make_distribution_version__(self):
...         return "1.16.0"
...
...     @property
...     def parameters(self):
...         return {"a": (-np.inf, np.inf),
...                 "b": {'endpoints':('a', np.inf), 'inclusive':(True, False)}}
...
...     @property
...     def support(self):
...         def left(*, a, b):
...             return a**3
...
...         def right(*, a, b):
...             return b**3
...         return (left, right)
...
...     def pdf(self, x, *, a, b):
...         return 1 / (3*(b - a)*np.cbrt(x)**2)
...
...     def cdf(self, x, *, a, b):
...         return (np.cbrt(x) - a) / (b - a)
>>>
>>> MyUniformCube = stats.make_distribution(MyUniformCube())
>>> X = MyUniformCube(a=-2, b=2)
>>> Y = stats.Uniform(a=-2, b=2)**3
>>> X.support()
(-8.0, 8.0)
>>> np.isclose(X.cdf(2.1), Y.cdf(2.1))
np.True_

Создать пользовательское распределение с несколькими параметризациями. Здесь мы создаем пользовательскую версию бета-распределения, которая имеет альтернативную параметризацию в терминах среднего mu и параметр дисперсии nu.

>>> class MyBeta:
...     @property
...     def __make_distribution_version__(self):
...         return "1.16.0"
...
...     @property
...     def parameters(self):
...         return ({"a": (0, np.inf), "b": (0, np.inf)},
...                 {"mu": (0, 1), "nu": (0, np.inf)})
...
...     def process_parameters(self, a=None, b=None, mu=None, nu=None):
...         if a is not None and b is not None:
...             nu = a + b
...             mu = a / nu
...         else:
...             a = mu * nu
...             b = nu - a
...         return dict(a=a, b=b, mu=mu, nu=nu)
...
...     @property
...     def support(self):
...         return {'endpoints': (0, 1)}
...
...     def pdf(self, x, a, b, mu, nu):
...         return special._ufuncs._beta_pdf(x, a, b)
...
...     def cdf(self, x, a, b, mu, nu):
...         return special.betainc(a, b, x)
>>>
>>> MyBeta = stats.make_distribution(MyBeta())
>>> X = MyBeta(a=2.0, b=2.0)
>>> Y = MyBeta(mu=0.5, nu=4.0)
>>> np.isclose(X.pdf(0.3), Y.pdf(0.3))
np.True_