Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Vdocument - in - Estadistica Con Python Ipdf
Vdocument - in - Estadistica Con Python Ipdf
In [1]: import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as s
In [2]: print np.__version__
import scipy
print scipy.__version__
print matplotlib.__version__
1.8.0
0.9.0
1.3.1
Referencias
Otro tutorial también sobre análisis estadístico y Python, en forma de notebook: Statistical Data Analysis in
Python (https://github.com/fonnesbeck/statistical-analysis-python-tutorial), con una parte interesante
dedicada a modelos
Y un curso con el material disponible en forma de notebooks: Coursera data analysis course, done in
Python (https://github.com/herrfz/dataanalysis). Aunque he descargado todos los notebooks en la carpeta
Coursera_dataanalysis, lo mejor es utilizar el índice del fichero readme
(https://github.com/herrfz/dataanalysis/blob/master/README.md)
El material completo del curso de Cursera está aquí: Coursera Data Analysis
(https://github.com/jtleek/dataanalysis) , aunque los pdf de las lecciones los he descargado en
Dropbox/personal/R proyectos
np.random.standard_normal((4,2))
np.random.uniform(size=10)
print np.random.randint(0,12,(3,4))
print np.random.random_integers(1,6, size=10)
[[ 5 2 0 8]
[ 8 11 11 7]
[11 9 0 9]]
[6 6 3 4 1 4 1 6 6 1]
[2 4 2 4 1 3 2 4 6 3]
[2 3 4 6 1 6 2 4 5 1]
Estadística descriptiva
Media
In [295]: np.random.seed(12345)
x =np.random.randint(0,12,(3,4))
print x
x = np.random.uniform(0,10,size=20)
noise = np.random.uniform(0, 3, size=20)
y = 5 + x + noise
plt.scatter(x,y);
In [45]: r, p = s.pearsonr(x,y)
print r, p
0.966159857324 4.88820573698e-12
Regresión lineal
Cálculo de los parámetros de la recta de regresión lineal se hacen con la función linregress() de Scipy.
http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.mstats.linregress.html
In [49]: print r_value
0.966159857324
In [53]: plt.scatter(x,y)
plt.plot([0, 10], [intercept, slope * 10 + intercept], '-r', lw=2);
Out[228]: Categorical:
[Madrid, Cuenca, Toledo, Madrid, Soria, Toledo, Madrid]
Levels (4): Index(['Cuenca', 'Madrid', 'Soria', 'Toledo'], dtype=object)
In [231]: # Los niveles de la variable categórica son los valores diferentes que
toma
cF.levels
Cuestiones de notación
X
es el conjunto de valores que puede tomar. Cada
valor ∈ R
X
es llamado un cuantil, y la probabilidad de que X tome el valor se designa por
P ( X = )
Vamos a utilizar el paquete stats de Scipy, que normalmente se importa con: "import scipy.stats as s".
Todas las distribuciones de probabilidad tienen en este paquete un tratamiento similar, con los mismos
métodos en todas ellas. Por ejemplo, para ver los métodos de la distribución normal, hacer:
print s.norm.doc
La distribución normal
0.683 %
Out[15]: 1.0006418287624492
"Freezing"
Con el fin de no tener que escribir en cada caso los parámetros loc y scale de una distribución, se puede
definir una variable aleatoria con "rv" del tipo y con los parámetros deseados, y despues referirnos a ella
con el nombre de la variable que le hayamos dado. Es decir, el objeto que hemos definido tiene los
mismos métodos que la distribución original
In [24]: mi_rv.rvs(size=10)
Out[24]: array([ 6.16432526, 5.48459398, 3.25193664, 3.58073744, 7.89030591,
6.35598259, 4.12032957, 4.99845849, 6.55752111, 3.26517431])
Distribución binomial
x=[0,1,2]
s.binom.pmf(x,2, 0.5)
Out[34]: array([ 0.25, 0.5 , 0.25])
Gráficos exploratorios
In [297]: x = np.random.normal(size=1e4)
y = np.random.normal(size=1e4)
plt.scatter(x, y);
Aquí no se ve nada, una posibilidad es representar una muestra (consideramos los valores de x e y
emparejados)
Vamos a ver lo que significa cada una de las variables devueltas por hist2d:
Ahora vamos a ver como podemos repr esentar un diagrama de contornos sobre la propia figura. Lo que
queremos representar como tercera magnitud son las frecuencias en cada celda...
fig.colorbar(im, ax=ax);
Pero, supongamos que solo queremos los contornos y no queremos representar la figura del histograma.
En ese caso el histograma lo generamos con numpy
Veamos ahora que significa normalizar los histogramas. Empecemos con el de contornos:
Ahora normalizamos. El array 2D ahora contiene la densidad en cada bin, es decir, el número de
observaciones en el bin dividido por el área del bin.
[[ 0.15612497 0.1617511 ]
[ 0.14065313 0.15612497]]
En efecto:
Out[232]: 0.99999999999999833
fig, ax = plt.subplots()
fig.set_size_inches(8, 8)
Heatmaps
imshow() se emplea para representar imágenes. En nuestro caso la imagen será una matriz bidimensional,
generada con histogram2d(), donde cada celda corresponde a un bin, y en ella hay un valor entero (una
cuenta de observaciones que caen dentro del bin). De modo que imshow() lo interpreta como una imagen
en escala de grises, aunque lo pinte en color, dependiendo del mapa de color que utilicemos. Esto tiene
como consecuencia que imshow() suaviza la imagen (los bins/pixels) no se muestran con claridad.
En cambio, matshow() representa la matriz sin hacer ningun suavizado. Por ello matshow es la mejor
opción cuando se quiere utilizar un mapa de colores para ver como se distribuyen las observaciones.
Clustering
In [90]: np.random.seed(12345)
clase1 = np.random.normal(loc=1,scale=0.2,size=(4,2))
clase2 = np.random.normal(loc=2,scale=0.2,size=(4,2))
clase3 = np.random.normal(loc=3,scale=0.2,size=(4,2))
clases = vstack((clase1, clase2, clase3))
x = clases[:,0]
y = clases[:,1]
plt.scatter(x,y, s=60)
for i in range(12):
plt.text(x[i]-0.025, y[i]+0.1,i)
Out[109]: x y
0 0.959058 1.095789
1 0.896112 0.888854
2 1.393156 1.278681
3 1.018582 1.056349
4 2.153805 2.249287
5 2.201438 1.740756
6 2.054998 2.045783
7 2.270583 2.177286
8 2.599673 2.925631
9 3.333805 2.912286
10 2.892052 3.095397
11 3.649789 2.795754
La función pdist() calcula la distancia de cada uno de los 12 puntos con respecto a los demás. Se crea un
array de ( − 1 ) / 2 valores
In [93]: dm = pdist(df,metric='euclidean')
dm.shape
Out[93]: (66,)
Out[101]: (11, 4)
Y construimos un dendrograma
In [102]: dendrogram(z);
Por curiosidad, las distancias también se pueden poner en forma de matriz cuadrada, aunque como se ha
visto, no es preciso para calcular el clustering:
k-clustering
El algoritmo "k-means" toma como entrada el número de clusters a generar, k (esto es su principal
limitación) y un conjunto de vectores resultado de observaciones (en nuestro caso los 12 pares de
coordenadas x,y). Devuelve un conjunto de k centroides, uno por cada cluster. Las observaciones son
clasificadas mediante el número del cluster (el index del centroide más próximo).
Este proceso se conoce a veces como "cuantificación" de los vectores de las observaciones. Al cluster
index de un vector se le llama el "código" y la tabla que asocia códigos y centroides se conoce como el
"code book"
In [107]: from scipy.cluster.vq import kmeans, vq
------------------------------------------------------------------------
---
TypeError Traceback (most recent call la
st)
<ipython-input-127-06fc099cba65> in <module>()
----> 1 codebook, varianza = kmeans(df,3)
/usr/local/lib/python2.7/dist-packages/numpy/core/fromnumeric.pyc in tak
e(a, indices, axis, out, mode)
116 except AttributeError:
117 return _wrapit(a, 'take', indices, axis, out, mode)
--> 118 return take(indices, axis, out, mode)
119
120
Para este ejemplo tenemos que leer un fichero de datos en el formato binario propietario de R: RData. Por
eso lo mejor es leerlo con R y despues pasarlo a un dataframe de Pandas
In [144]: %load_ext rmagic
In [149]: %%R
load("./datos/samsungData.rda")
write.csv(samsungData,file="./datos/samsungData.csv")
In [152]: samsungData.tail()
In [153]: samsungData.shape
In [162]: samsungData.columns[0:10]
In [163]: samsungData['activity'].value_counts()
Out[163]: laying 1407
standing 1374
sitting 1286
walk 1226
walkup 1073
walkdown 986
dtype: int64
Hay una línea por sujeto y lectura de los accelerómetros, y a cada vector de observaciones se asigna una
actividad. A continuación vamos a ir probando variables del sujeto 1, y viendo si estas variables discriminan
bien entre actividades:
for act, df in grouped:
ax1.scatter(df.ix[:,0], df.index, c=dic_col[act], label=act)
ax2.scatter(df.ix[:,1], df.index, c=dic_col[act], label=act)
ax1.set_xlabel(samsungData.columns[0])
ax1.set_ylabel(u'# Observación')
ax2.set_xlabel(samsungData.columns[1])
ax2.legend(loc='upper left')
Conclusión: las dos primeras variables no nos permiten discriminar por tipos de actividad
Ahora vamos a probar a hacer un agrupamiento jerárquico basado en las tres primeras columnas, a ver si
esto nos permite separar por grupos con un tipo de actividad
In [243]: dm = pdist(subj1.ix[:,0:3],metric='euclidean')
z = linkage(dm, method='complete')
# plt.figure(figsize=(5, 10)) # Una forma de dar el tamaño de la fi
gura
dendrogram(z, orientation='right', color_threshold=0.2,
leaf_label_func=lambda n : 'X' * (actF.labels[n] + 1));
fig = plt.gcf() # Get current figure
fig.set_size_inches(5,10) # Otra forma de dar el tamaño
for act, df in grouped:
ax1.scatter(df.ix[:,9], df.index, c=dic_col[act], label=act)
ax2.scatter(df.ix[:,10], df.index, c=dic_col[act], label=act)
ax1.set_xlabel(samsungData.columns[9])
ax1.set_ylabel(u'# Observación')
ax2.set_xlabel(samsungData.columns[10])
ax2.legend(loc='upper left')
Continuaremos este ejemplo más adelante una vez hayamos visto el análisis de componentes principales
(PCA)
In []: