Descargamos los datos de http://www.amstat.org/publications/jse/v2n1/datasets.mcintyre.html.
In [1]:
import urllib.request
urllib.request.urlretrieve("http://www.amstat.org/publications/jse/datasets/cigarettes.dat.txt", "cigarettes.dat")
Out[1]:
In [2]:
!wc -l cigarettes.dat
In [3]:
cat cigarettes.dat
Vamos a cargar los en Python con pandas. pandas es una biblioteca de Python para trabajar con tablas de datos (llamados DataFrames
) de forma cómoda. En Pybonacci escribimos un tutorial de pandas desde lo más básico a usos un poco más intermedios.
In [4]:
import pandas as pd
In [5]:
df = pd.read_csv("cigarettes.dat", delim_whitespace=True, header=None,
names=["Marca", "Alquitrán", "Nicotina", "Peso", "Monóxido"])
df.head()
Out[5]:
Además, vamos a añadir el tipo de cigarro para que la tabla quede como la presentada en el curso.
In [6]:
df["Clases"] = ['Rubio', 'Negro', 'Negro', 'Rubio', 'Rubio',
'Negro', 'Rubio', 'Rubio', 'Negro', 'Rubio',
'Rubio', 'Rubio', 'Rubio', 'Rubio', 'Rubio',
'Rubio', 'Negro', 'Rubio', 'Negro', 'Rubio',
'Negro', 'Rubio', 'Negro', 'Negro', 'Rubio']
In [7]:
df[["Clases", "Alquitrán", "Nicotina", "Peso", "Monóxido"]]
Out[7]:
Los DataFrame
de pandas tienen un método describe()
que imprime algunas medidas estadísticas interesantes de nuestra tabla:
In [8]:
df.describe().transpose()
Out[8]:
Podemos añadir también el error estándar de la media y la varianza:
In [9]:
df.sem()
Out[9]:
In [10]:
df.var()
Out[10]:
Por tanto, contestando a las preguntas del informe:
1) El tamaño muestral es de 25.
2) La variable con mayor variabilidad es el alquitrán: se aprecia mejor en la tabla de la varianza.
3) La media más representativa de los datos es la del peso: el error estándar de la media es el menor de las cuatro variables.
4) La media más estable es la del peso, por lo mismo que se ha dicho en el apartado anterior.
Ahora volvemos a utilizar el método describe()
pero esta vez especificamos manualmente los percentiles, seleccionamos solo las columnas que nos interesan y presentamos la tabla:
In [11]:
(df.describe(percentiles=[.05, .10, .25, .50, .75, .90, .95])
[["Monóxido", "Alquitrán", "Nicotina", "Peso"]]
.transpose()
[["5%", "10%", "25%", "50%", "75%", "90%", "95%"]])
Out[11]:
Recuperamos además la mediana y el recorrido intercuartílico:
In [12]:
df.median()
Out[12]:
In [13]:
iqr = df.quantile(.75) - df.quantile(.25)
iqr
Out[13]:
Observamos una gran variabilidad de los contenidos de alquitrán y monóxido de carbono, mientras que las cantidades de nicotina son más estables y el peso de los cigarrillos prácticamente no cambia. Los resultados son similares a los obtenidos estudiando la media y su dispersión.
Por último, utilizamos la biblioteca matplotlib para representar los diagramas de cajas. Por defecto son de tipo Tukey, es decir: los bigotes llegan hasta 1.5 veces el recorrido intercuartílico por encima del percentil 75 y por debajo del percentil 25.
In [14]:
%matplotlib inline
import matplotlib.pyplot as plt
plt.style.use("fivethirtyeight")
In [15]:
plt.figure(figsize=(8, 8))
plt.subplot(2, 2, 1)
df.boxplot("Monóxido", return_type='axes')
plt.subplot(2, 2, 2)
df.boxplot("Alquitrán", return_type='axes')
plt.ylim(0, 35) # Para ver una medida discordante
plt.subplot(2, 2, 3)
df.boxplot("Nicotina", return_type='axes')
plt.subplot(2, 2, 4)
df.boxplot("Peso", return_type='axes')
plt.ylim(0, 1.20) # Importante
Out[15]:
Tanto el monóxido como el peso presentan distribuciones bastante simétricas, mientras que el alquitrán tiene un claro sesgo positivo. Especial atención merece el peso en este caso, pues una correcta escala vertical es esencial para no percibir una variabilidad errónea. Tanto en los datos de nicotina como en los de alquitrán se aprecian sendos valores discordantes, que invitarían a no comprar esa marca de cigarrillos.
In [16]:
df[df["Alquitrán"] > df["Alquitrán"].quantile(.75) + 1.5 * iqr["Alquitrán"]]
Out[16]: