"statistics" --- Funciones de estadística matemática
****************************************************

Nuevo en la versión 3.4.

**Código fuente:** Lib/statistics.py

======================================================================

Este módulo proporciona funciones para calcular estadísticas
matemáticas de datos numéricos (de tipo "Real").

Este módulo no pretende ser competidor o sustituto de bibliotecas de
terceros como NumPy o SciPy, ni de paquetes completos de software
propietario para profesionales como Minitab, SAS o Matlab. Este módulo
se ubica a nivel de calculadoras científicas gráficas.

A menos que se indique explícitamente lo contrario, las funciones de
este módulo manejan objetos "int", "float", "Decimal" y "Fraction". No
se garantiza un correcto funcionamiento con otros tipos (numéricos o
no). El comportamiento de estas funciones con colecciones mixtas que
contengan objetos de diferente tipo no está definido y depende de la
implementación. Si tus datos de entrada consisten en una mezcla de
varios tipos, puedes usar "map()" para asegurarte de que el resultado
sea consistente, por ejemplo: "map(float, input_data)".


Promedios y medidas de tendencia central
========================================

Estas funciones calculan el promedio o el valor típico de una
población o muestra.

+-------------------------+-----------------------------------------------------------------+
| "mean()"                | Media aritmética ("promedio") de los datos.                     |
+-------------------------+-----------------------------------------------------------------+
| "fmean()"               | Media aritmética usando coma flotante, más rápida.              |
+-------------------------+-----------------------------------------------------------------+
| "geometric_mean()"      | Media geométrica de los datos.                                  |
+-------------------------+-----------------------------------------------------------------+
| "harmonic_mean()"       | Media armónica de los datos.                                    |
+-------------------------+-----------------------------------------------------------------+
| "median()"              | Mediana (valor central) de los datos.                           |
+-------------------------+-----------------------------------------------------------------+
| "median_low()"          | Mediana baja de los datos.                                      |
+-------------------------+-----------------------------------------------------------------+
| "median_high()"         | Mediana alta de los datos.                                      |
+-------------------------+-----------------------------------------------------------------+
| "median_grouped()"      | Mediana, o percentil 50, de los datos agrupados.                |
+-------------------------+-----------------------------------------------------------------+
| "mode()"                | Moda única (valor más común) de datos discretos o nominales.    |
+-------------------------+-----------------------------------------------------------------+
| "multimode()"           | Lista de modas (valores más comunes) de datos discretos o       |
|                         | nominales.                                                      |
+-------------------------+-----------------------------------------------------------------+
| "quantiles()"           | Divide los datos en intervalos equiprobables.                   |
+-------------------------+-----------------------------------------------------------------+


Medidas de dispersión
=====================

Estas funciones calculan una medida de cuánto tiende a desviarse la
población o muestra de los valores típicos o promedios.

+-------------------------+-----------------------------------------------+
| "pstdev()"              | Desviación típica poblacional de los datos.   |
+-------------------------+-----------------------------------------------+
| "pvariance()"           | Varianza poblacional de los datos.            |
+-------------------------+-----------------------------------------------+
| "stdev()"               | Desviación típica muestral de los datos.      |
+-------------------------+-----------------------------------------------+
| "variance()"            | Varianza muestral de los datos.               |
+-------------------------+-----------------------------------------------+


Detalles de las funciones
=========================

Nota: Las funciones no requieren que se ordenen los datos que se les
proporcionan. Sin embargo, para facilitar la lectura, la mayoría de
los ejemplos muestran secuencias ordenadas.

statistics.mean(data)

   Retorna la media aritmética muestral de *data*, que puede ser una
   secuencia o un iterable.

   La media aritmética es la suma de los valores dividida entre el
   número de observaciones. Es comúnmente denominada "promedio",
   aunque hay muchas formas de definir el promedio matemáticamente. Es
   una medida de tendencia central de los datos.

   Se lanza una excepción "StatisticsError" si *data* está vacío.

   Algunos ejemplos de uso:

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

   Nota:

     La media aritmética se ve fuertemente afectada por la presencia
     de valores atípicos en la muestra y no es un estimador robusto de
     tendencia central: la media no es necesariamente un ejemplo
     representativo de la muestra. Consulta "median()" y "mode()" para
     obtener medidas más robustas de tendencia central.La media
     muestral proporciona una estimación no sesgada de la media real
     de la población. Por lo tanto, al calcular el promedio de todas
     las muestras posibles, "mean(sample)" converge con el promedio
     real de toda la población. Si *data* representa a una población
     completa, en lugar de a una muestra, entonces "mean(data)"
     equivale a calcular la media poblacional verdadera μ.

statistics.fmean(data)

   Convierte los valores de *data* a flotantes y calcula la media
   aritmética.

   Esta función se ejecuta más rápido que "mean()" y siempre retorna
   un "float". *data* puede ser una secuencia o un iterable. Si el
   conjunto de datos de entrada está vacío, se lanza una excepción
   "StatisticsError".

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

   Nuevo en la versión 3.8.

statistics.geometric_mean(data)

   Convierte los valores de *data* a flotantes y calcula la media
   geométrica.

   La media geométrica indica la tendencia central o valor típico de
   *data* utilizando el producto de los valores (en oposición a la
   media aritmética, que utiliza su suma).

   Lanza una excepción "StatisticsError" si el conjunto de datos de
   entrada está vacío, o si contiene un cero o un valor negativo.
   *data* puede ser una secuencia o un iterable.

   No se toman medidas especiales para garantizar que el resultado sea
   completamente preciso. (Sin embargo, esto puede cambiar en una
   versión futura.)

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

   Nuevo en la versión 3.8.

statistics.harmonic_mean(data)

   Retorna la media armónica de *data*, que debe ser una secuencia o
   un iterable de números que pertenezcan al conjunto de los números
   reales.

   La media armónica es el inverso o recíproco de la media aritmética
   ("mean()") de los inversos multiplicativos de los datos. Por
   ejemplo, la media armónica de tres valores *a*, *b* y *c* es
   "3/(1/a + 1/b + 1/c)". El resultado es cero si uno de los valores
   es cero.

   La media armónica es un tipo de promedio, una medida de la
   tendencia central de los datos. Generalmente es adecuada para
   calcular promedios de tasas o fracciones, por ejemplo, velocidades.

   Supongamos que un automóvil viaja 10 km a 40 km/h, luego otros 10
   km a 60 km/h. ¿Cuál es su velocidad media?

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

   Supongamos que un inversor compra la misma cantidad de acciones de
   tres empresas diferentes, con unos PER (ratio precio-beneficio) de
   2.5, 3 y 10. ¿Cuál es el PER promedio para la cartera del inversor?

      >>> harmonic_mean([2.5, 3, 10])  # For an equal investment portfolio.
      3.6

   Una excepción "StatisticsError" es lanzada si *data* está vacío o
   algún elemento es menor que cero.

   El algoritmo actual tiene una salida anticipada cuando encuentra un
   cero en la entrada. Esto significa que no se comprueba la validez
   de las entradas posteriores al cero. (Este comportamiento puede
   cambiar en el futuro.)

   Nuevo en la versión 3.6.

statistics.median(data)

   Retorna la mediana (valor central) de los datos numéricos,
   utilizando el método clásico de "media de los dos del medio". Si
   *data* está vacío, se lanza una excepción "StatisticsError". *data*
   puede ser una secuencia o un iterable.

   La mediana es una medida de tendencia central robusta y es menos
   sensible a la presencia de valores atípicos que la media. Cuando el
   número de casos es impar, se retorna el valor central:

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

   Cuando el número de observaciones es par, la mediana se interpola
   calculando el promedio de los dos valores centrales:

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

   Este enfoque es adecuado para datos discretos, siempre que se
   acepte que la mediana no es necesariamente parte de las
   observaciones.

   Si los datos son ordinales (se pueden ordenar) pero no numéricos
   (no se pueden sumar), considera usar "median_low()" o
   "median_high()" en su lugar.

statistics.median_low(data)

   Retorna la mediana baja de los datos numéricos. Se lanza una
   excepción "StatisticsError" si *data* está vacío. *data* puede ser
   una secuencia o un iterable.

   La mediana baja es siempre un valor presente en el conjunto de
   datos. Cuando el número de casos es impar, se retorna el valor
   central. Cuando el número de casos es par, se retorna el menor de
   los dos valores centrales.

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

   Utiliza la mediana baja cuando tus datos sean discretos y prefieras
   que la mediana sea un valor representado en tus observaciones, en
   lugar de ser el resultado de una interpolación.

statistics.median_high(data)

   Retorna la mediana alta de los datos. Lanza una excepción
   "StatisticsError" si *data* está vacío. *data* puede ser una
   secuencia o un iterable.

   La mediana alta es siempre un valor presente en el conjunto de
   datos. Cuando el número de casos es impar, se retorna el valor
   central. Cuando el número de casos es par, se retorna el mayor de
   los dos valores centrales.

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

   Utiliza la mediana alta cuando tus datos sean discretos y prefieras
   que la mediana sea un valor representado en tus observaciones, en
   lugar de ser el resultado de una interpolación.

statistics.median_grouped(data, interval=1)

   Retorna la mediana de los datos continuos agrupados, calculada como
   el percentil 50, usando interpolación. Se lanza una excepción
   "StatisticsError" si *data* está vacío. *data* puede ser una
   secuencia o un iterable.

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

   En el siguiente ejemplo, los valores se redondean para que cada
   valor represente la mitad de un grupo. Por ejemplo, 1 es la mitad
   del grupo 0.5--1.5, 2 es la mitad del grupo 1.5--2.5, 3 es la mitad
   de 2.5--3.5, etc. En los datos proporcionados a continuación, el
   valor medio está en algún lugar del grupo que va de 3,5 a 4,5 y se
   estima mediante interpolación:

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

   El argumento opcional *interval* representa el intervalo de clase y
   el valor predeterminado es 1. Cambiar el intervalo de clase
   cambiará la interpolación, como es natural:

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

   Esta función no comprueba si los valores están separados por al
   menos un *interval*.

   **CPython implementation detail:** Bajo algunas circunstancias,
   "median_grouped()" puede convertir algunos de los valores
   proporcionados en flotantes. Es probable que este comportamiento
   cambie en el futuro.

   Ver también:

     * "Statistics for the Behavioral Sciences", Frederick J Gravetter
       y Larry B Wallnau (8ª edición).

     * La función SSMEDIAN del programa de hojas de cálculo Gnumeric
       de Gnome, incluyendo esta discusión.

statistics.mode(data)

   Retorna el valor más común del conjunto de datos discretos o
   nominales *data*.La moda (cuando existe) es el valor más
   representativo y sirve como medida de tendencia central.

   Si hay varias modas con la misma frecuencia, retorna la primera
   encontrada en *data*. Si deseas la menor o la mayor de ellas, usa
   "min(multimode(data))" o "max(multimode(data))". Se lanza una
   excepción "StatisticsError" si la entrada *data* está vacía.

   "mode" asume que los datos de entrada son discretos y retorna un
   solo valor. Esta es la definición habitual de la moda que se enseña
   en las escuelas:

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

   La moda tiene la particularidad de ser la única estadística de este
   módulo que se puede calcular sobre datos nominales (no numéricos):

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

   Distinto en la versión 3.8: Ahora maneja conjuntos de datos
   multimodales, retornando la primera moda encontrada. Anteriormente,
   se lanzaba una excepción "StatisticsError" cuando se daba esta
   situación.

statistics.multimode(data)

   Retorna una lista de los valores más frecuentes en el orden en que
   aparecen en *data*. Retornará varios resultados en el caso de que
   existan varias modas, o una lista vacía si *data* está vacío:

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

   Nuevo en la versión 3.8.

statistics.pstdev(data, mu=None)

   Retorna la desviación típica poblacional (la raíz cuadrada de la
   varianza poblacional). Consultar "pvariance()" para los argumentos
   y otros detalles.

      >>> pstdev([1.5, 2.5, 2.5, 2.75, 3.25, 4.75])
      0.986893273527251

statistics.pvariance(data, mu=None)

   Retorna la varianza poblacional de *data*, que debe ser una
   secuencia no vacía o un iterable de números reales. La varianza, o
   momento de segundo orden respecto a la media, es una medida de la
   variabilidad (o dispersión) de los datos. Una alta varianza indica
   una amplia dispersión de valores; una varianza baja indica que los
   valores están agrupados alrededor de la media.

   El segundo argumento opcional *mu*, que normalmente será la media
   de *data*, también se puede utilizar para calcular el momento de
   segundo orden alrededor de un punto que no es la media. Si no se
   proporciona o es "None" (el valor predeterminado), la media
   aritmética se calcula automáticamente.

   Utiliza esta función para calcular la varianza de toda la
   población. Para estimar la varianza de una muestra, la función
   "variance()" suele ser una opción mejor.

   Lanza una excepción "StatisticsError" si *data* está vacío.

   Ejemplos:

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

   Si ya has calculado la media de tus datos, puedes pasarla como
   segundo argumento opcional *mu* para evitar que se tenga que volver
   a calcular:

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

   Se admiten decimales (Decimal) y fracciones (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)

   Nota:

     Esta función retorna la varianza poblacional σ² cuando se aplica
     a toda la población. Si se aplica solo a una muestra, el
     resultado es la varianza muestral s², conocida también como
     varianza con N grados de libertad.Si se conoce de antemano la
     verdadera media poblacional μ, se puede usar esta función para
     calcular la varianza muestral, pasando la media poblacional
     conocida como segundo argumento. Suponiendo que las observaciones
     provienen de una selección aleatoria uniforme de la población, el
     resultado será una estimación no sesgada de la varianza
     poblacional.

statistics.stdev(data, xbar=None)

   Retorna la desviación típica muestral (la raíz cuadrada de la
   varianza muestral). Consultar "variance()" para los argumentos y
   otros detalles.

      >>> stdev([1.5, 2.5, 2.5, 2.75, 3.25, 4.75])
      1.0810874155219827

statistics.variance(data, xbar=None)

   Retorna la varianza muestral de *data*, que debe ser un iterable de
   al menos dos números reales. La varianza, o momento de segundo
   orden respecto a la media, es una medida de la variabilidad
   (difusión o dispersión) de los datos. Una alta varianza indica que
   los datos están dispersos; una baja varianza indica que los datos
   están agrupados estrechamente alrededor de la media.

   Si se proporciona el segundo argumento opcional *xbar*, este debe
   ser la media aritmética de *data*. Si no se proporciona o es "None"
   (el valor predeterminado), la media aritmética se calcula
   automáticamente.

   Utiliza esta función cuando tus datos sean una muestra de una
   población. Para calcular la varianza de toda la población, consulta
   "pvariance()".

   Lanza una excepción "StatisticsError" si *data* tiene menos de dos
   valores.

   Ejemplos:

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

   Si previamente se ha calculado la media de los datos, puede pasarse
   como segundo argumento opcional *xbar* para evitar que se tenga que
   volver a calcular:

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

   Esta función no comprueba si el valor pasado al argumento *xbar*
   corresponde al promedio. El uso de valores arbitrarios para *xbar*
   produce resultados imposibles o incorrectos.

   La función maneja decimales (Decimal) y fracciones (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)

   Nota:

     Esta es la varianza muestral s² con la corrección de Bessel,
     también conocida como varianza con N-1 grados de libertad.
     Suponiendo que las observaciones son representativas de la
     población (es decir, independientes y distribuidas de forma
     idéntica), el resultado es una estimación no sesgada de la
     varianza.Si conoces de antemano la verdadera media poblacional μ,
     debes pasarla a "pvariance()" mediante el parámetro *mu* para
     obtener la varianza muestral.

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

   Divide *data* en *n* intervalos continuos equiprobables. Retorna
   una lista de "n - 1" límites que delimitan los intervalos
   (cuantiles).

   Establece *n* en 4 para obtener los cuartiles (el valor
   predeterminado), en 10 para obtener los deciles y en 100 para
   obtener los percentiles (lo que produce 99 valores que separan
   *data* en 100 grupos del mismo tamaño). Si *n* es menor que 1, se
   lanza una excepción "StatisticsError".

   *data* puede ser cualquier iterable que contenga los valores de la
   muestra. Para que los resultados sean significativos, el número de
   observaciones en la muestra *data* debe ser mayor que *n*. Si no
   hay al menos dos observaciones se lanza una excepción
   "StatisticsError".

   Los límites de los intervalos se interpolan linealmente a partir de
   los dos valores más cercanos de la muestra. Por ejemplo, si un
   límite es un tercio de la distancia entre los valores 100 y 112 de
   la muestra, el límite será 104.

   El argumento *method* indica el método que se utilizará para
   calcular los cuantiles y se puede modificar para especificar si se
   deben incluir o excluir valores de *data* extremos, altos y bajos,
   de la población.

   El valor predeterminado para *method* es "exclusive" y es aplicable
   a los datos muestreados de una población que puede tener valores
   más extremos que los encontrados en las muestras. La proporción de
   la población que se encuentra por debajo del *i-ésimo* valor de *m*
   valores ordenados se calcula mediante la fórmula "i / (m + 1)". Por
   ejemplo, asumiendo que hay 9 valores en la muestra, este método los
   ordena y los asocia con los siguientes percentiles: 10%, 20%, 30%,
   40%, 50%, 60%, 70%, 80%, 90%.

   Si se usa "inclusive" como valor para el parámetro *method*, se
   asume que los datos corresponden a una población completa o que los
   valores extremos de la población están representados en la muestra.
   El valor mínimo de *data* se considera entonces como percentil 0 y
   el máximo como percentil 100. La proporción de la población que se
   encuentra por debajo del *i-ésimo* valor de *m* valores ordenados
   se calcula mediante la fórmula "(i - 1) / (m - 1)". Suponiendo que
   tenemos 11 valores en la muestra, este método los ordena y los
   asocia con los siguientes percentiles: 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]

   Nuevo en la versión 3.8.


Excepciones
===========

Se define una sola excepción:

exception statistics.StatisticsError

   Subclase de "ValueError" para excepciones relacionadas con la
   estadística.


Objetos "NormalDist"
====================

"NormalDist" es una herramienta para crear y manipular distribuciones
normales de una variable aleatoria. Esta clase gestiona la desviación
típica y la media de un conjunto de observaciones como una sola
entidad.

Las distribuciones normales surgen del Teorema del límite central y
tienen una amplia gama de aplicaciones en estadística.

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

   Retorna un nuevo objeto *NormalDist* donde *mu* representa la media
   aritmética y *sigma* representa la desviación típica.

   Se lanza una excepción "StatisticsError" si *sigma* es negativo.

   mean

      Una propiedad de solo lectura para la media aritmética de una
      distribución normal.

   median

      Una propiedad de solo lectura para la mediana de una
      distribución normal.

   mode

      Una propiedad de solo lectura para la moda de una distribución
      normal.

   stdev

      Una propiedad de solo lectura para la desviación típica de una
      distribución normal.

   variance

      Una propiedad de solo lectura para la varianza de una
      distribución normal. Es igual al cuadrado de la desviación
      típica.

   classmethod from_samples(data)

      Crea una instancia de distribución normal con los parámetros
      *mu* y *sigma* estimados a partir de *data* usando "fmean()" y
      "stdev()".

      *data* puede ser cualquier *iterable* de valores que se puedan
      convertir al tipo "float". Se lanza una excepción
      "StatisticsError" si *data* no contiene al menos dos elementos,
      esto se debe a que se necesita al menos un punto para estimar un
      valor central y al menos dos puntos para estimar la dispersión.

   samples(n, *, seed=None)

      Genera *n* muestras aleatorias para una media y una desviación
      típica proporcionadas. Retorna un objeto "list" de valores
      "float".

      Si se proporciona *seed*, su valor se usa para inicializar una
      nueva instancia del generador de números aleatorios subyacente.
      Esto permite producir resultados reproducibles incluso en un
      contexto de paralelismo con múltiples hilos.

   pdf(x)

      Haciendo uso de una función de densidad de probabilidad (FPD o
      PDF en inglés), calcula la verosimilitud relativa de que una
      variable aleatoria *X* caiga en una región cercana al valor *x*
      proporcionado. Matemáticamente, esto corresponde al límite de la
      razón "P(x <= X < x+dx) / dx" cuando *dx* tiende a cero.

      La verosimilitud relativa se calcula como la probabilidad de que
      una observación pertenezca a un intervalo estrecho dividida
      entre el ancho del intervalo (de ahí el término "densidad").
      Como la verosimilitud es relativa a los otros puntos, su valor
      puede ser mayor que *1.0*.

   cdf(x)

      Usando una función de distribución acumulada (FDA, CDF en
      inglés), calcula la probabilidad de que una variable aleatoria
      *X* sea menor o igual que *x*. Matemáticamente, se escribe "P(X
      <= x)".

   inv_cdf(p)

      Calcula la función de distribución acumulada inversa, también
      conocida como función cuantil o función punto porcentual.
      Matemáticamente, se escribe "x : P(X <= x) = p".

      Calcula el valor *x* de la variable aleatoria *X* tal que la
      probabilidad de que la variable sea menor o igual a este valor
      es igual a la probabilidad *p* dada.

   overlap(other)

      Mide la concordancia entre dos distribuciones de probabilidad
      normales. Retorna un valor entre 0.0 y 1.0 que indica el área de
      superposición de dos funciones de densidad de probabilidad.

   quantiles(n=4)

      Divide la distribución normal en *n* intervalos continuos
      equiprobables. Retorna una lista de (n - 1) cuantiles que
      separan los intervalos.

      Establece *n* en 4 para obtener los cuartiles (el valor
      predeterminado), en 10 para obtener los deciles y en 100 para
      obtener los percentiles (lo que produce 99 límites que separan
      los datos en 100 grupos del mismo tamaño).

   Las instancias de la clase "NormalDist" soportan la suma, resta,
   multiplicación y división por una constante. Estas operaciones se
   pueden utilizar para traducir o escalar, por ejemplo:

      >>> temperature_february = NormalDist(5, 2.5)             # Celsius
      >>> temperature_february * (9/5) + 32                     # Fahrenheit
      NormalDist(mu=41.0, sigma=4.5)

   No se admite la división de una constante entre una instancia de
   "NormalDist" debido a que el resultado no sería una distribución
   normal.

   Dado que las distribuciones normales se derivan de las propiedades
   aditivas de variables independientes, es posible sumar o restar dos
   variables independientes con distribución normal representadas por
   instancias de "NormalDist". Por ejemplo :

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

   Nuevo en la versión 3.8.


Ejemplos de uso de "NormalDist"
-------------------------------

"NormalDist" permite resolver fácilmente problemas probabilísticos
clásicos.

Por ejemplo, sabiendo que los datos históricos de los exámenes SAT
siguen una distribución normal con una media de 1060 y una desviación
típica de 195, determinar el porcentaje de estudiantes con
puntuaciones entre 1100 y 1200, redondeado al número entero más
cercano:

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

Determinar los cuartiles y deciles de las puntuaciones del 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]

Con la finalidad de estimar la distribución de un modelo que es
difícil de resolver analíticamente, "NormalDist" puede generar
muestras de entrada para una simulación utilizando el método
Montecarlo:

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

Las distribuciones normales se pueden utilizar para aproximar
distribuciones binomiales cuando el tamaño de la muestra es grande y
la probabilidad de un ensayo exitoso es cercana al 50%.

Por ejemplo, 750 personas asisten a una conferencia sobre código
abierto y se dispone de dos salas con capacidad para 500 personas cada
una. En la primera sala hay una charla sobre Python, en la otra una
sobre Ruby. En conferencias pasadas, el 65% de las personas
prefirieron escuchar las charlas sobre Python. Suponiendo que las
preferencias de la población no hayan cambiado, ¿cuál es la
probabilidad de que la sala de Python permanezca por debajo de su
capacidad máxima?

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

   >>> # 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, 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

Las distribuciones normales a menudo están involucradas en el
aprendizaje automático.

Wikipedia detalla un buen ejemplo de un clasificador bayesiano
ingenuo. El objetivo es predecir el género de una persona a partir de
características físicas que siguen una distribución normal, como la
altura, el peso y el tamaño del pie.

Disponemos de un conjunto de datos de entrenamiento que contiene las
medidas de ocho personas. Se supone que estas medidas siguen una
distribución normal, por lo que podemos sintetizar los datos usando
"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])

A continuación, nos encontramos con un nuevo individuo del que
conocemos las medidas de sus características pero no su género:

   >>> ht = 6.0        # height
   >>> wt = 130        # weight
   >>> fs = 8          # foot size

Partiendo de una probabilidad a priori del 50% de ser hombre o mujer,
calculamos la probabilidad a posteriori como el producto de la
probabilidad a priori y la verosimilitud de las diferentes medidas
dado el género:

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

La predicción final es la que tiene mayor probabilidad a posteriori.
Este enfoque se denomina máximo a posteriori o MAP:

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