Medidas de centralidad y dispersión
Índice de contenido
Librerías de estadística en Python
En Python, hay varias librerías con módulos de estadística. A continuación, enumeramos algunas de ellas:
- La librería estándar de Python incluye el módulo statistics. Tal y como se indica en la documentación oficial, este módulo no pretende ser competencia de otras bibliotecas de terceros, como NumPy o SciPy, sino que está más enfocado en gráficas y en servir como calculadora científica.
- NumPy proporciona varias funciones que permiten aplicar cálculos estadísticos.
- SciPy tiene el módulo stats, que incluye un gran número de funciones estadísticas.
- pandas, como NumPy, también cuenta con funciones para realizar cálculos estadísticos.
En primer lugar, vamos a crear unos datos con los cuales podamos trabajar. A continuación, iremos revisando los conceptos fundamentales de estadística y, a su vez, veremos ejemplos aplicados a conjuntos de datos, utilizando para ello el módulo statistics de la librería estándar de Python, el módulo stats de SciPy y las funciones de pandas.
import statistics
import numpy as np
from scipy import stats
import pandas as pd
data_df = pd.DataFrame({
"col1": [1,2,3,2,2,100],
"col2": [4.,5,6,7,8,9],
"col3": [3,3,2,2,6,6]
})
data_df
| col1 | col2 | col3 | |
|---|---|---|---|
| 0 | 1 | 4.0 | 3 |
| 1 | 2 | 5.0 | 3 |
| 2 | 3 | 6.0 | 2 |
| 3 | 2 | 7.0 | 2 |
| 4 | 2 | 8.0 | 6 |
| 5 | 100 | 9.0 | 6 |
data_serie = data_df.col2
data_serie
0 4.0
1 5.0
2 6.0
3 7.0
4 8.0
5 9.0
Name: col2, dtype: float64
data_vector = data_serie.to_numpy()
data_vector
array([4., 5., 6., 7., 8., 9.])
Medidas de promedio y ubicación central
Nos permiten comprender cuáles son los valores centrales del conjunto de datos, calculando un promedio o valor típico.
Media aritmética
Concepto
La media aritmética es la suma de todos los datos dividida por el número de datos. Comúnmente, se conoce como “promedio”, aunque hay muchos promedios matemáticos distintos.

Ejemplos
len(data_df.col2)
6
(4. + 5. + 6. + 7. + 8. + 9.)/len(data_df.col2)
6.5
Cálculo con statistics
statistics.mean(data_serie)
6.5
statistics.mean(data_vector)
6.5
statistics.mean(data_df)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-15-6ef8c4f21b07> in <module>
----> 1 statistics.mean(data_df)
~\anaconda3\envs\statistics\lib\statistics.py in mean(data)
314 if n < 1:
315 raise StatisticsError('mean requires at least one data point')
--> 316 T, total, count = _sum(data)
317 assert count == n
318 return _convert(total/n, T)
~\anaconda3\envs\statistics\lib\statistics.py in _sum(data, start)
164 for typ, values in groupby(data, type):
165 T = _coerce(T, typ) # or raise TypeError
--> 166 for n,d in map(_exact_ratio, values):
167 count += 1
168 partials[d] = partials_get(d, 0) + n
~\anaconda3\envs\statistics\lib\statistics.py in _exact_ratio(x)
246 return (x, None)
247 msg = "can't convert type '{}' to numerator/denominator"
--> 248 raise TypeError(msg.format(type(x).__name__))
249
250
TypeError: can't convert type 'str' to numerator/denominator
data_df.apply(lambda x: statistics.mean(x))
col1 18.333333
col2 6.500000
col3 3.666667
dtype: float64
Cálculo con scipy
stats.tmean(data_serie)
6.5
stats.tmean(data_vector)
6.5
stats.tmean(data_df)
9.5
(stats.tmean(data_df.col1) + stats.tmean(data_df.col2) + stats.tmean(data_df.col3))/3
9.5
stats.tmean(data_df.col1, limits= (0, 5))
2.0
Cálculo con numpy
np.mean(data_serie)
6.5
np.mean(data_vector)
6.5
np.mean(data_df)
col1 18.333333
col2 6.500000
col3 3.666667
dtype: float64
Cálculo con pandas
data_serie.mean()
6.5
# Método de numpy
data_vector.mean()
6.5
data_df.mean()
col1 18.333333
col2 6.500000
col3 3.666667
dtype: float64
Media geométrica
Concepto
La media geométrica da información acerca de la tendencia central o el valor típico de los datos, pero utiliza el producto de los valores, a diferencia de la media aritmética que usa la suma. Para un conjunto de n datos, se calcula como la raíz n-ésima del producto de todos los datos:

Se utiliza especialmente para promediar porcentajes.
Ejemplos
Cálculo con statistics
statistics.geometric_mean(data_serie)
6.26520516202487
statistics.geometric_mean(data_vector)
6.26520516202487
statistics.geometric_mean(data_df)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
~\anaconda3\envs\statistics\lib\statistics.py in fmean(data)
330 try:
--> 331 n = len(data)
332 except TypeError:
TypeError: object of type 'map' has no len()
During handling of the above exception, another exception occurred:
TypeError Traceback (most recent call last)
<ipython-input-40-c35206b3c6b4> in <module>
----> 1 statistics.geometric_mean(data_df)
~\anaconda3\envs\statistics\lib\statistics.py in geometric_mean(data)
359 """
360 try:
--> 361 return exp(fmean(map(log, data)))
362 except ValueError:
363 raise StatisticsError('geometric mean requires a non-empty dataset '
~\anaconda3\envs\statistics\lib\statistics.py in fmean(data)
337 for n, x in enumerate(iterable, start=1):
338 yield x
--> 339 total = fsum(count(data))
340 else:
341 total = fsum(data)
~\anaconda3\envs\statistics\lib\statistics.py in count(iterable)
335 def count(iterable):
336 nonlocal n
--> 337 for n, x in enumerate(iterable, start=1):
338 yield x
339 total = fsum(count(data))
TypeError: must be real number, not str
data_df.apply(lambda x: statistics.geometric_mean(x))
col1 3.659052
col2 6.265205
col3 3.301927
dtype: float64
Cálculo con scipy
stats.gmean(data_serie)
6.26520516202487
stats.gmean(data_df)
array([3.65905165, 6.26520516, 3.30192725])
Cálculo con numpy
# No tiene esta función
Cálculo con pandas
# No tiene esta función
Media armónica
Concepto
La media armónica de un conjunto de valores es el inverso de la media aritmética de los inversos de dichos valores:

Se utiliza a menudo para promediar velocidades y tiempos.
Ejemplos
Cálculo con statistics
statistics.harmonic_mean(data_serie)
6.0263053009167
statistics.harmonic_mean(data_vector)
6.0263053009167
statistics.harmonic_mean(data_df)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-47-7a4189f443bc> in <module>
----> 1 statistics.harmonic_mean(data_df)
~\anaconda3\envs\statistics\lib\statistics.py in harmonic_mean(data)
404 raise TypeError('unsupported type')
405 try:
--> 406 T, total, count = _sum(1/x for x in _fail_neg(data, errmsg))
407 except ZeroDivisionError:
408 return 0
~\anaconda3\envs\statistics\lib\statistics.py in _sum(data, start)
162 partials_get = partials.get
163 T = _coerce(int, type(start))
--> 164 for typ, values in groupby(data, type):
165 T = _coerce(T, typ) # or raise TypeError
166 for n,d in map(_exact_ratio, values):
~\anaconda3\envs\statistics\lib\statistics.py in <genexpr>(.0)
404 raise TypeError('unsupported type')
405 try:
--> 406 T, total, count = _sum(1/x for x in _fail_neg(data, errmsg))
407 except ZeroDivisionError:
408 return 0
~\anaconda3\envs\statistics\lib\statistics.py in _fail_neg(values, errmsg)
286 """Iterate over values, failing if any are less than zero."""
287 for x in values:
--> 288 if x < 0:
289 raise StatisticsError(errmsg)
290 yield x
TypeError: '<' not supported between instances of 'str' and 'int'
Cálculo con scipy
stats.hmean(data_serie)
6.026305300916699
stats.hmean(data_vector)
6.026305300916699
stats.hmean(data_df)
array([2.1101993, 6.0263053, 3. ])
Cálculo con numpy
# No tiene esta función
Cálculo con pandas
# No tiene esta función
Mediana
Concepto
La mediana es el valor que divide el conjunto de datos en dos partes con el mismo número de valores. Si se ordenan todos los datos de menor a mayor:
- En el caso de que el conjunto tenga un número impar de valores, la mediana es el dato que está justo “en el medio”, dejando tantos datos por debajo como por encima de su valor.
- En el caso de que el conjunto tenga un número par de valores, la mediana es la media aritmética de los dos datos centrales.
4 5 6 7 8 9
mediana = statistics.mean([6,7])
mediana
6.5
statistics.mean(data_df.col2)
6.5
statistics.mean(data_df.col1)
18.333333333333332
1 2 2 2 3 100
# Mediana 2
Ejemplos
Cálculo con statistics
statistics.median(data_serie)
6.5
statistics.median(data_df.col1)
2.0
# No tiene sentido aplicarlo así
statistics.median(data_df)
'col2'
data_df.apply(lambda x: statistics.median(x))
col1 2.0
col2 6.5
col3 3.0
dtype: float64
Cálculo con scipy
# Que no os lleve a confusión! No es lo mismo que la mediana
stats.median_abs_deviation(data_df.col1)
0.5
Cálculo con numpy
np.median(data_serie)
6.5
np.median(data_vector)
6.5
np.median(data_df)
3.5
np.median([data_df.col1, data_df.col2, data_df.col3])
3.5
Cálculo con pandas
data_serie.median()
6.5
data_df.median()
col1 2.0
col2 6.5
col3 3.0
dtype: float64
Moda
Concepto
La moda es el valor que más veces se repite en el conjunto de datos, es decir, el valor más frecuente.
Ejemplos
Cálculo con statistics
En versiones antiguas, si no encuentra una única moda, devuelve un error. En versiones nuevas, devuelve la primera moda que encuentra.
statistics.mode(data_df.col1)
2
statistics.mode(data_df.col2)
4.0
statistics.mode(data_df.col3)
3
Para obtener una lista con todos los valores más frecuentes, hay que utilizar la función multimode. Por ejemplo:
statistics.multimode(data_df.col2)
[4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
statistics.multimode(data_df.col3)
[3, 2, 6]
Cálculo con scipy
Si hay más de una moda, devuelve solo la que tenga valor más pequeño.
stats.mode(data_df.col2)
ModeResult(mode=array([4.]), count=array([1]))
stats.mode(data_df.col3)
ModeResult(mode=array([2], dtype=int64), count=array([2]))
Cálculo con numpy
# ---
Cálculo con pandas
Si hay más de una moda, las devuelve todas.
data_serie.mode()
0 4.0
1 5.0
2 6.0
3 7.0
4 8.0
5 9.0
dtype: float64
data_df.mode()
| col1 | col2 | col3 | |
|---|---|---|---|
| 0 | 2.0 | 4.0 | 2.0 |
| 1 | NaN | 5.0 | 3.0 |
| 2 | NaN | 6.0 | 6.0 |
| 3 | NaN | 7.0 | NaN |
| 4 | NaN | 8.0 | NaN |
| 5 | NaN | 9.0 | NaN |
Medidas de variabilidad
Nos dan información acerca de la dispersión que presentan los datos, es decir, permiten calcular una medida de cuánto tienden a desviarse los datos con respecto a los valores típicos o promedio.
Varianza
Concepto
La varianza es una medida de variabilidad que indica la dispersión de un conjunto de datos con respecto a su media.

Varianza muestral:

Varianza poblacional:

statistics.mean(data_df.col2)
6.5
n = len(data_df.col2)
n
6
# Varianza muestral
((4.0 - 6.5)**2 + (5.0 - 6.5)**2 + (6.0 - 6.5)**2 + (7.0 - 6.5)**2 + (8.0 - 6.5)**2 + (9.0 - 6.5)**2) / (n-1)
3.5
# Varianza poblacional
((4.0 - 6.5)**2 + (5.0 - 6.5)**2 + (6.0 - 6.5)**2 + (7.0 - 6.5)**2 + (8.0 - 6.5)**2 + (9.0 - 6.5)**2) / (n)
2.9166666666666665
Ejemplos
Cálculo con statistics
# Varianza muestral
statistics.variance(data_df.col2)
3.5
# Varianza poblacional
statistics.pvariance(data_df.col2)
2.9166666666666665
Cálculo con scipy
# Muestral (1 grado de libertad)
stats.tvar(data_df.col2)
3.5
# Varianza poblacional (0 grados de libertad)
stats.tvar(data_df.col2, ddof=0)
2.9166666666666665
stats.tvar(data_df.col1, limits=(0, 5))
0.5
stats.tvar(data_df.col1)
1601.0666666666668
Cálculo con pandas
# Muestral (1 grado de libertad)
data_serie.var()
3.5
# Varianza poblacional (0 grados de libertad)
data_df.var(ddof=0)
col1 1334.222222
col2 2.916667
col3 2.888889
dtype: float64
Desviación típica
Concepto
La desviación estándar o desviación típica es la medida de dispersión más común e indica cómo de dispersos se encuentran los datos con respecto a la media. Cuando mayor sea la desviación estándar, mayor será la dispersión de los datos.
Básicamente, es la raíz cuadrada de la varianza, por lo que las unidades serán las mismas que las de los datos de origen.
Desviación típica muestral:

Desviación típica poblacional:

# Varianza muestral
var_muestral =((4.0 - 6.5)**2 + (5.0 - 6.5)**2 + (6.0 - 6.5)**2 + (7.0 - 6.5)**2 + (8.0 - 6.5)**2 + (9.0 - 6.5)**2) / (n-1)
var_muestral
3.5
# Varianza poblacional
var_pob = ((4.0 - 6.5)**2 + (5.0 - 6.5)**2 + (6.0 - 6.5)**2 + (7.0 - 6.5)**2 + (8.0 - 6.5)**2 + (9.0 - 6.5)**2) / (n)
var_pob
2.9166666666666665
# Desviación típica muestral
np.sqrt(var_muestral)
1.8708286933869707
# Desviación típica poblacional
np.sqrt(var_pob)
1.707825127659933
Ejemplos
Cálculo con statistics
# Desviación estándar muestral
statistics.stdev(data_df.col2)
1.8708286933869707
# Desviación estándar poblacional
statistics.pstdev(data_df.col2)
1.707825127659933
Cálculo con scipy
# Desviación estándar muestral
stats.tstd(data_df.col2)
1.8708286933869707
# Desviación estándar poblacional
stats.tstd(data_df.col2, ddof=0)
1.707825127659933
# Desviación estándar poblacional sin recortar
stats.tstd(data_df.col1, ddof=0)
36.527006751473934
# Desviación estándar poblacional recortada
stats.tstd(data_df.col1, limits=(0, 5), ddof=0)
0.6324555320336759
Cálculo con pandas
# Desviación estándar muestral
data_serie.std()
1.8708286933869707
# Desviación estándar poblacional
data_serie.std(ddof=0)
1.707825127659933
# Desviación estándar muestral
data_df.std()
col1 40.013331
col2 1.870829
col3 1.861899
dtype: float64
Covarianza
Concepto
¡Importante! La covarianza está tratada en profundidad en otro notebook.
La covarianza es una medida que indica en qué grado dos variables aleatorias varían de forma conjunta respecto a sus medias. Se puede calcular mediante la siguiente fórmula:

En esencia, nos permite conocer de qué manera evoluciona una variable en función de lo que hace otra variable, pudiendo tomar los siguiente valores:
Covarianza(X,Y)=0: no hay relación entre las variables X e Y.
Covarianza(X,Y)<0: cuando X aumenta, Y disminuye. Hay una relación negativa.
Covarianza(X,Y)>0: cuando X aumenta, Y aumenta. Hay una relación positiva.
La covarianza tiene las siguientes propiedades:
- Cov(X,b)=0, donde b es una constante.
- Cov(X,X)=Var(X)
- Cov(X,Y)=Cov(Y,X)
- Cov(b·X,c·Y)=c·b·Cov(X,Y)
- Cov(b+X,c+Y)=Cov(X,Y)
Es importante tener en cuenta que las covarianzas de distintas variables no son comparables, puesto que el valor de la covarianza es un valor absoluto que depende de la unidad de medida de las variables.
