Estadistica con python I.pdf
-
Upload
eduardomartincalleja -
Category
Documents
-
view
819 -
download
44
Transcript of Estadistica con python I.pdf
-
5/21/2018 Estadistica con python I.pdf
1/30
Tutorial sobre estadstica en Python: I
Distribuciones, grficos, clustering
In [1]: importpandasaspdimportnumpyasnpimportmatplotlib.pyplotaspltimportscipy.statsass
In [2]: printnp.__version__importscipyprintscipy.__version__printmatplotlib.__version__
Referencias
Este es un tutorial sobre anlisis estadstico en Python: tutorial R. Olson
(http://www.randalolson.com/2012/08/06/statistical-analysis-made-easy-in-python/)
Esta es la documentacin de la librera estadstica de SciPy: scipy.stats
(http://docs.scipy.org/doc/scipy/reference/tutorial/stats.html)
Otro tutorial tambin sobre anlisis estadstico 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
El blog Micropore (http://micropore.wordpress.com/) tiene bastantes cosas de Python y astronoma
Generacin de valores aleatorios con Numpy
1.8.0
0.9.01.3.1
https://github.com/jtleek/dataanalysishttps://github.com/jtleek/dataanalysishttps://github.com/jtleek/dataanalysishttps://github.com/jtleek/dataanalysishttps://github.com/jtleek/dataanalysishttps://github.com/jtleek/dataanalysishttps://github.com/jtleek/dataanalysishttps://github.com/jtleek/dataanalysishttps://github.com/jtleek/dataanalysishttps://github.com/jtleek/dataanalysishttps://github.com/jtleek/dataanalysishttps://github.com/jtleek/dataanalysishttps://github.com/jtleek/dataanalysishttps://github.com/jtleek/dataanalysishttps://github.com/herrfz/dataanalysis/blob/master/README.mdhttps://github.com/herrfz/dataanalysis/blob/master/README.mdhttps://github.com/herrfz/dataanalysis/blob/master/README.mdhttps://github.com/herrfz/dataanalysishttps://github.com/herrfz/dataanalysishttps://github.com/herrfz/dataanalysishttps://github.com/herrfz/dataanalysishttps://github.com/herrfz/dataanalysishttps://github.com/fonnesbeck/statistical-analysis-python-tutorialhttps://github.com/fonnesbeck/statistical-analysis-python-tutorialhttp://docs.scipy.org/doc/scipy/reference/tutorial/stats.htmlhttp://micropore.wordpress.com/https://github.com/jtleek/dataanalysishttps://github.com/herrfz/dataanalysis/blob/master/README.mdhttps://github.com/herrfz/dataanalysishttps://github.com/fonnesbeck/statistical-analysis-python-tutorialhttp://docs.scipy.org/doc/scipy/reference/tutorial/stats.htmlhttp://www.randalolson.com/2012/08/06/statistical-analysis-made-easy-in-python/ -
5/21/2018 Estadistica con python I.pdf
2/30
In [3]: # generacin de valores aleatorios segn distribucin normal# normal(loc=0.0, scale=1.0, size=None)# loc es la media, scale la desviacin estndar# size es un un valor entero
# o una tupla con el shape deseado
alturas = np.random.normal(188, 3, 20)printalturas
In [4]: # Cuando deseamos valores segn la distribucin normal estndar# (mean=0, stdev =1), podemos utilizar# standard_normal(size), donde size puede ser un valor entero o un shape
np.random.standard_normal((4,2))
In [22]: # Generacin de valores aleatorios segn distribucin binomial# binomial(n, p, size)
coinFlips = np.random.binomial(1, 0.5, 10)printcoinFlips
In [9]: # Generacin de valores aleatorios segn la distribucin uniforme# En un intervalo semiabierto [low, high)# uniform(low=0.0, high=1.0, size=1)# size puede ser un entero o una tupla indicando un shape
np.random.uniform(size=10)
[ 190.09944441 193.31053145 192.10140399 189.08948296 194.01804315 187.08032995 190.53477337 188.38027873 190.74397206 191.10964306 196.58267576 187.70675913 191.99139412 188.14624532 190.57930883 191.81629275 185.77887953 189.25968599 183.90044742 187.989887 ]
Out[4]: array([[-0.12656278, 1.04534887], [ 0.96472613, -0.95483344], [ 0.40339144, -2.29152082], [-1.15241441, 0.73026361]])
[0 1 1 1 1 1 0 0 1 1]
Out[9]: array([ 0.5526518 , 0.59462721, 0.13537618, 0.91364061, 0.59570865, 0.24854146, 0.7054177 , 0.17873533, 0.70354042, 0.30468929])
-
5/21/2018 Estadistica con python I.pdf
3/30
In [15]: # Generacin de valores aleatorios enteros segn la distribucin uniforme# en el intervalo semiabierto [low, high)# o bien, si high se omite, en [0, low)# size es un entero o una tupla indicando un shape#randint(low, high=None, size=None)
printnp.random.randint(0,12,(3,4))
# Tambin se puede utilizar random_integers, similar a la anterior# pero que genera valores enteros en el intervalo cerrado#[low, high]print
printnp.random.random_integers(1,6, size=10)
Obtencin de muestras con Numpy
In [16]: # random.choice(a, size=None, replace=True, p=None)# a es un array 1-D obligatoriamente, o bien un num. entero# (ver ejemplo siguiente)# size es un valor entero o una tupla indicando un shape
# p es un array de probabilidades de igual longitud que a# si se omite se supone distribucin uniforme para a# replace=False si se desea una muestra sin remplazamiento
np.random.choice(alturas, size=5, replace=False)
In [18]: # Otra posibilidad es hacer a igual a un valor entero n# Viene bien para por ejemplo indexar con l
# En este caso las muestras se toman del array arange(n)
np.random.choice(10, size = (2,3), replace=False)
Fijar una semilla
[[ 5 2 0 8][ 8 11 11 7][11 9 0 9]]
[6 6 3 4 1 4 1 6 6 1]
Out[16]: array([ 196.58267576, 190.74397206, 189.25968599, 191.99139412, 189.08948296])
Out[18]: array([[1, 2, 8], [3, 9, 4]])
-
5/21/2018 Estadistica con python I.pdf
4/30
In [71]: # Vamos obteniendo valores diferentes en cada llamada a la funcinnp.random.seed(12345)printnp.random.random_integers(1,6, size=10)printnp.random.random_integers(1,6, size=10)printnp.random.random_integers(1,6, size=10)
In [76]: # Y si volvemos a activar la semilla, recomenzamos la misma secuencianp.random.seed(12345)printnp.random.random_integers(1,6, size=10)printnp.random.random_integers(1,6, size=10)printnp.random.random_integers(1,6, size=10)
In [77]: # Sin embargo una nueva celda del notebook# comienza simepre con una semilla aleatoria# a menos que volvamos a fijar una semillaprintnp.random.random_integers(1,6, size=10)printnp.random.random_integers(1,6, size=10)printnp.random.random_integers(1,6, size=10)
Estadstica descriptiva
Media
[3 6 6 2 5 2 6 3 6 2]
[2 4 2 4 1 3 2 4 6 3]
[2 3 4 6 1 6 2 4 5 1]
[3 6 6 2 5 2 6 3 6 2][2 4 2 4 1 3 2 4 6 3]
[2 3 4 6 1 6 2 4 5 1]
[4 5 5 6 4 4 2 4 6 3]
[6 4 1 6 3 5 6 4 4 5][4 1 4 1 1 4 6 3 5 5]
-
5/21/2018 Estadistica con python I.pdf
5/30
In [295]: np.random.seed(12345)x =np.random.randint(0,12,(3,4))printx
# Obtener la media de todos los valores del arrayprint"media total: ", x.mean()
# Obtener la media de cada columnaprint"media calculada variando la fila: ", x.mean(axis=0)
# Obtener la media de cada filaprint"media calculada variando la columna: ", x.mean(axis=1)
Varianza y desviacin estndar
In [291]: # varianza muestral (dividiendo por n-1)printx.var(ddof=1)printx.var(ddof=1, axis=0)printx.var(ddof=1, axis=1)
In [292]: # Desviacin tpica muestralprintx.std(ddof=1)printx.std(ddof=1, axis=0)printx.std(ddof=1, axis=1)
Relacin lineal entre dos variables
En este apartado utilizaremos el paquete estadstico de scipy, que se importa con:
"import scipy.stats as s"
Coeficiente de correlacin r de Pearson
[[ 2 5 1 4][ 9 5 2 1][ 6 1 11 9]]media total: 4.66666666667
media calculada variando la fila: [ 5.66666667 3.66666667 4.666666674.66666667]
media calculada variando la columna: [ 3. 4.25 6.75]
12.2424242424[ 12.33333333 5.33333333 30.33333333 16.33333333][ 3.33333333 12.91666667 18.91666667]
3.49891758154[ 3.51188458 2.30940108 5.50757055 4.04145188][ 1.82574186 3.59397644 4.34932945]
-
5/21/2018 Estadistica con python I.pdf
6/30
In [54]: # Construyamos dos arrays x e y con los que experimentar
np.random.seed(12345)
x = np.random.uniform(0,10,size=20)noise = np.random.uniform(0, 3, size=20)y = 5 + x + noiseplt.scatter(x,y);
In [45]: r, p = s.pearsonr(x,y)printr, p
El coeficiente de determinacin es el cuadrado del coeficiente de correlacin , y se interpreta como elporcentaje de variabilidad de la variable que es explicado por el modelo lineal.
In [39]: # El valor de r**2 es el coeficiente de determinacin,# que indica la fortaleza de la relacin entre ambas variables
printu"El coeficiente de determinacin es %.2f" %r**2
# El 93% de la variacin de y se puede explicar por la variable x,# el resto ser debido a causas desconocidas, variables ocultas# o variabilidad inherente
Regresin lineal
Clculo de los parmetros de la recta de regresin lineal se hacen con la funcin linregress() de Scipy.
http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.mstats.linregress.html
In [48]: slope, intercept, r_value, p_value, std_err = s.linregress(x, y)
0.966159857324 4.88820573698e-12
El coeficiente de determinacin es 0.93
-
5/21/2018 Estadistica con python I.pdf
7/30
In [49]: printr_value
In [53]: plt.scatter(x,y)plt.plot([0, 10], [intercept, slope * 10 + intercept], '-r', lw=2);
Factores / variables categricas
In [228]: # Los factores de R equivalen a las variables categricas de Pandasciudades = np.array(['Madrid', 'Cuenca', 'Toledo', 'Madrid', 'Soria', 'Toledo', 'Madrid'])
cF = pd.Categorical.from_array(ciudades)cF
In [231]: # Los niveles de la variable categrica son los valores diferentes quetomacF.levels
In [232]: # Los labels son el contenido de la variable, codificada numricamente# haciendo referencia a los levelscF.labels
Las distribuciones de probabilidad con Scipy
Cuestiones de notacin
0.966159857324
Out[228]: Categorical:[Madrid, Cuenca, Toledo, Madrid, Soria, Toledo, Madrid]Levels (4): Index(['Cuenca', 'Madrid', 'Soria', 'Toledo'], dtype=object)
Out[231]: Index([u'Cuenca', u'Madrid', u'Soria', u'Toledo'], dtype=object)
Out[232]: array([1, 0, 3, 1, 2, 3, 1])
-
5/21/2018 Estadistica con python I.pdf
8/30
Dada una variable aleatoria , el rango de , es el conjunto de valores que puede tomar. Cada
valor es llamado un cuantil, y la probabilidad de que tome el valor se designa por
Un "random variate" es un resultado particular de una variable aleatoria.
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
mtodos en todas ellas. Por ejemplo, para ver los mtodos de la distribucin normal, hacer:
print s.norm.doc
La distribucin normal
In [12]: # pdf: Probability Density Function
# s.norm.pdf(array x de cuantiles, loc, scale)# loc es la media, scale es la desviacin estndarx = np.linspace(-5, 5, num=100)normalDensity = s.norm.pdf(x, loc=0, scale=1)plt.plot(x, normalDensity)plt.xlabel('cuantiles');
In [13]: # cdf: Cumulative Distribution Function# s.norm.pdf(array de cuantiles, loc, scale)# loc es la media, scale la desviacin estndar
# Probabilidad de |X| < sigmasigma = 4print"%.3f%%" %(s.norm.cdf(sigma, loc=0, scale=sigma)-s.norm.cdf(-sigma, loc=0, scale=sigma))
X X R
X
R
X
X
P ( X = )
0.683 %
-
5/21/2018 Estadistica con python I.pdf
9/30
In [15]: # ppf: Percent Point Function (Inversa de CDF)
s.norm.ppf(0.683/2 + 0.5, loc=0, scale=1)
In [16]: # Devuelve la media y varianza de la distribucins.norm.stats(loc=3, scale=4)
In [17]: # rvs: generacin de valores aleatorios (random variates)# bajo la variable aleatoria considerada ( la normal en el ejemplo)
s.norm.rvs(loc=5, scale=2, size=10)
"Freezing"
Con el fin de no tener que escribir en cada caso los parmetros loc y scale de una distribucin, se puede
definir una variable aleatoria con "rv" del tipo y con los parmetros 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 mtodos que la distribucin original
In [21]: mi_rv = s.norm(loc=5, scale=2)mi_rv.stats()
In [24]: mi_rv.rvs(size=10)
Distribucin binomial
In [34]: # pmf: Probability Mass Function# Sustituye a pdf en las variables discretas# pmf(x, n, pr)
x=[0,1,2]s.binom.pmf(x,2, 0.5)
Grficos exploratorios
Representar muchos puntos
Out[15]: 1.0006418287624492
Out[16]: (array(3.0), array(16.0))
Out[17]: array([ 2.07049884, 5.71139329, 5.58134749, 6.19376692, 5.92728227, 4.37584035, 4.60381517, 7.66738297, 8.44622194, 1.63065077])
Out[21]: (array(5.0), array(4.0))
Out[24]: array([ 6.16432526, 5.48459398, 3.25193664, 3.58073744, 7.89030591, 6.35598259, 4.12032957, 4.99845849, 6.55752111, 3.26517431])
Out[34]: array([ 0.25, 0.5 , 0.25])
-
5/21/2018 Estadistica con python I.pdf
10/30
In [297]: x = np.random.normal(size=1e4)
y = np.random.normal(size=1e4)plt.scatter(x, y);
# con plt.plot(x,y, 'o') hubieramos obtenido el mismo resultado
Aqu no se ve nada, una posibilidad es representar una muestra (consideramos los valores de x e y
emparejados)
In [298]: r = np.random.choice(10**4, size=1000, replace=False)plt.scatter(x[r], y[r]);
Out[297]:
-
5/21/2018 Estadistica con python I.pdf
11/30
In [309]: # Tambin puede intentarse variar la transperencia# y tamao de los puntosplt.scatter(x, y, edgecolors='none', alpha=0.025, s=60);
In [310]: # Y otra opcin es utilizar un grfico de R%load_extrmagic%Rpushx y%RsmoothScatter(x, y, nrpoints=0)
The rmagic extension is already loaded. To reload it, use: %reload_ext rmagic
-
5/21/2018 Estadistica con python I.pdf
12/30
In [8]: # Se puede aadir como opcin un color map, por ejemplo:# cmap=plt.cm.Greys
# cmap=plt.cm.Reds# # cmap=plt.cm.hotplt.hexbin(x, y)# El color en cada hexgono corresponde a la frecuencia # Tambin se puede utilizar la opcin bins=n para normalizarcb=plt.colorbar()cb.set_label('frecuencias')fig = plt.gcf()# Get current figurefig.set_size_inches(10,8)
Ahora, el mismo ejemplo utilizando figure y axis explcitamente:
-
5/21/2018 Estadistica con python I.pdf
13/30
In [9]: fig, ax = plt.subplots()fig.set_size_inches(10,8)im = ax.hexbin(x,y)fig.colorbar(im, ax=ax);
A continuacin haremos un histograma 2d, de baja resolucin para poder analizarlo
-
5/21/2018 Estadistica con python I.pdf
14/30
In [40]: fig, ax = plt.subplots()fig.set_size_inches(10,8)hist, xedges, yedges, im = ax.hist2d(x,y, bins=(10,10), range=[[-4.,4.], [-4., 4.]])fig.colorbar(im, ax=ax);
Vamos a ver lo que significa cada una de las variables devueltas por hist2d:
In [26]: # hist es la frecuencia en cada bin, en este caso un grid de 10x10printhist.shapeprinthist
(10, 10)[[ 0. 0. 0. 1. 2. 5. 0. 0. 0. 0.][ 0. 0. 7. 18. 17. 19. 10. 6. 0. 0.][ 0. 4. 26. 69. 136. 151. 61. 16. 6. 0.][ 0. 10. 62. 234. 449. 455. 220. 67. 9. 2.][ 2. 17. 134. 445. 845. 823. 477. 135. 27. 2.][ 4. 19. 130. 456. 824. 824. 447. 147. 23. 2.][ 0. 9. 93. 239. 451. 435. 253. 72. 14. 1.][ 1. 4. 24. 90. 137. 151. 78. 20. 3. 0.][ 1. 0. 6. 12. 13. 20. 15. 6. 0. 0.][ 0. 0. 0. 0. 0. 3. 2. 0. 0. 0.]]
-
5/21/2018 Estadistica con python I.pdf
15/30
In [31]: # xbins e ybins son los lmites de los intervalos semiabiertos# que definen cada binprintxbinsprintybins
Ahora vamos a ver como podemos representar un diagrama de contornos sobre la propia figura. Lo que
queremos representar como tercera magnitud son las frecuencias en cada celda...
Hay un ejemplo en: http://micropore.wordpress.com/2011/10/01/2d-density-plot-or-2d-histogram/
In [263]: fig, ax = plt.subplots()fig.set_size_inches(10, 8)
# Rango de valores en cada ejerango = [[-4., 4.],[-4., 4.]]
# Generamos el histograma y el grfico a la vez# Valores de bins elevados dan mucha fragmentacin en las curvashist, xedges, yedges, im = ax.hist2d(x,y, bins=(30,30), range=rango, cmap=plt.cm.Greys)
fig.colorbar(im, ax=ax);
extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]]
# Niveles para las curvas de nivelniveles = [30, 50, 70, 90]colores=['green', 'blue', 'yellow', 'red']
cset = ax.contour(hist, niveles, linewidths=2, extent=extent, colors=colores)ax.clabel(cset, inline=1, fontsize=15, fmt='%d')
[-4. -3.2 -2.4 -1.6 -0.8 0. 0.8 1.6 2.4 3.2 4. ][-4. -3.2 -2.4 -1.6 -0.8 0. 0.8 1.6 2.4 3.2 4. ]
-
5/21/2018 Estadistica con python I.pdf
16/30
Pero, supongamos que solo queremos los contornos y no queremos representar la figura del histograma.
En ese caso el histograma lo generamos con numpy
Out[263]:
-
5/21/2018 Estadistica con python I.pdf
17/30
In [262]: fig, ax = plt.subplots()fig.set_size_inches(8, 8)
# Rango de valores en cada ejerango = [[-4., 4.],[-4., 4.]]
# Generamos un histograma wD de frecuencias con numpyhist, xedges, yedges= np.histogram2d(x,y, bins=(30,30), range=rango)
extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]]
# Niveles para las curvas de nivel de las frecuenciasniveles = [30, 50, 70, 90]colores=['green', 'blue', 'yellow', 'red']cset = ax.contour(hist, niveles, linewidths=2, extent=extent, colors=colores)ax.clabel(cset, inline=1, fontsize=15, fmt='%d');
Veamos ahora que significa normalizar los histogramas. Empecemos con el de contornos:
-
5/21/2018 Estadistica con python I.pdf
18/30
In [200]: rango = [[-4., 4.],[-4., 4.]]hist, xedges, yedges= np.histogram2d(x,y, bins=(30,30), range=rango)total_count = sum(hist)printtotal_countprinthist[14:16,14:16]
Ahora normalizamos. El array 2D ahora contiene la densidad en cada bin, es decir, el nmero de
observaciones en el bin dividido por el rea del bin.
In [229]: rango = [[-4., 4.],[-4., 4.]]hist, xedges, yedges= np.histogram2d(x,y, bins=(30,30), range=rango)
histn, xedges, yedges= np.histogram2d(x,y, bins=(30,30), range=rango, normed=True)print"el resultado es:"printhistn[14:16,14:16]
# obtenido del siguiente modo:hist_suma_1 = hist/sum(hist)print'\n'area = 8. * 8. / (30*30)printhist_suma_1[14:16,14:16]/area
De hecho, si consideramos que la matriz histn es una matriz de densidades, cumplir:
suma(densidad_i x area bin_i) = 64/900 x suma(densidad_i) = 64/900 * sum(histn) = 1
En efecto:
In [232]: 64./900 * sum(histn)
9998.0
[[ 111. 115.][ 100. 111.]]
el resultado es:[[ 0.15612497 0.1617511 ][ 0.14065313 0.15612497]]
[[ 0.15612497 0.1617511 ][ 0.14065313 0.15612497]]
Out[232]: 0.99999999999999833
-
5/21/2018 Estadistica con python I.pdf
19/30
In [236]: # Este es un ejemplo con valores normalizados. Las curvas dicen# Que por ejemplo la densidad es superior a 0.01 dentro de la curva
fig, ax = plt.subplots()fig.set_size_inches(8, 8)
# Rango de valores en cada ejerango = [[-4., 4.],[-4., 4.]]
histn, xedges, yedges= np.histogram2d(x,y, bins=(30,30), range=rango, normed=True)extent = [yedges[0], yedges[-1], xedges[0], xedges[-1]]
# Niveles para las curvas de nivel de las densidadesniveles = [0.01,0.05, 0.1, 0.15]colores=['green', 'blue', 'yellow', 'red']cset = ax.contour(histn, niveles, linewidths=2, extent=extent, colors=colores)ax.clabel(cset, inline=1, fontsize=15, fmt='%.2f');
Heatmaps
-
5/21/2018 Estadistica con python I.pdf
20/30
En lugar de emplear la funcin plt.hist2d, tambin se puede generar un histograma 2D con
numpy.histogram2dy, y representarlo con imshow():
imshow() se emplea para representar imgenes. 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 tienecomo consecuencia que imshow() suaviza la imagen (los bins/pixels) no se muestran con claridad.
In [270]: # generamos datos de test con la distribucin normal estndarx = np.random.randn(8873)y = np.random.randn(8873)heatmap, xedges, yedges = np.histogram2d(x, y, bins=50)# genera un heatmap 50x50extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]]plt.imshow(heatmap, extent=extent);
En cambio, matshow() representa la matriz sin hacer ningun suavizado. Por ello matshow es la mejor
opcin cuando se quiere utilizar un mapa de colores para ver como se distribuyen las observaciones.
In [273]: plt.matshow(heatmap, extent=extent);
Clustering
-
5/21/2018 Estadistica con python I.pdf
21/30
Agrupamiento jerrquico (hierarchical clustering)
La idea del clustering o agrupamiento jerrquico es construir un arbol de smilaridades basado en
distancias entre cada dos observaciones.
Referencia a la librera scipy.cluster.hierarchy
(http://docs.scipy.org/doc/scipy/reference/cluster.hierarchy.html#module-scipy.cluster.hierarchy)
Referencia a la librera scipy.spatial.distance
(http://docs.scipy.org/doc/scipy/reference/spatial.distance.html)
In [89]: fromscipy.spatial.distanceimportpdist, squareformfromscipy.cluster.hierarchyimportlinkage, dendrogram
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)fori inrange(12): plt.text(x[i]-0.025, y[i]+0.1,i)
Vamos a crear un dataframe con las 12 observaciones:
http://docs.scipy.org/doc/scipy/reference/spatial.distance.htmlhttp://docs.scipy.org/doc/scipy/reference/cluster.hierarchy.html#module-scipy.cluster.hierarchy -
5/21/2018 Estadistica con python I.pdf
22/30
In [109]: df = pd.DataFrame(clases, columns=['x', 'y'])df
La funcin pdist() calcula la distancia de cada uno de los 12 puntos con respecto a los dems. Se crea un
array de valores
In [93]: dm = pdist(df,metric='euclidean')dm.shape
A continuacin, hacemos el clustering
In [101]: z = linkage(dm, method='complete')z.shape
Y construimos un dendrograma
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
( 1 ) / 2
Out[93]: (66,)
Out[101]: (11, 4)
-
5/21/2018 Estadistica con python I.pdf
23/30
In [102]: dendrogram(z);
In [106]: # Se pueden buscar otras orientacionesdendrogram(z, orientation='right');
Por curiosidad, las distancias tambin se pueden poner en forma de matriz cuadrada, aunque como se ha
visto, no es preciso para calcular el clustering:
In [94]: distxy = squareform(dm)
distxy.shape
In [95]: # Como vemos, es una matriz simtrica con 0 en la diagonaldistxy[0:3,0:3]
k-clustering
Out[94]: (12, 12)
Out[95]: array([[ 0. , 0.21629657, 0.47105247], [ 0.21629657, 0. , 0.63167861], [ 0.47105247, 0.63167861, 0. ]])
-
5/21/2018 Estadistica con python I.pdf
24/30
El algoritmo "k-means" toma como entrada el nmero de clusters a generar, k (esto es su principal
limitacin) 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 nmero del cluster (el index del centroide ms prximo).
Este proceso se conoce a veces como "cuantificacin" de los vectores de las observaciones. Al cluster
index de un vector se le llama el "cdigo" y la tabla que asocia cdigos y centroides se conoce como el
"code book"
In [107]: fromscipy.cluster.vqimportkmeans, vq
In [127]: codebook, varianza = kmeans(df,3)
In [128]: # parece que a la funcin kmeans no le gustan los dtaframes de pandascodebook, varianza = kmeans(np.vstack(zip(x,y)),3)
In [129]: # sin embargo... pasandolo a array de numpy, funcionacodebook, varianza = kmeans(df.values,3)
In [132]: # En realidad, esto no lo necesitamos para nadaprintdistortion
---------------------------------------------------------------------------TypeError Traceback (most recent call last) in ()----> 1 codebook, varianza = kmeans(df,3)
/usr/lib/python2.7/dist-packages/scipy/cluster/vq.pyc in kmeans(obs, k_or_guess, iter, thresh) 505 for i in range(iter): 506 #the intial code book is randomly selected from observations--> 507 guess = take(obs, randint(0, No, k), 0) 508 book, dist = _kmeans(obs, guess, thresh = thresh) 509 if dist < best_dist:
/usr/local/lib/python2.7/dist-packages/numpy/core/fromnumeric.pyc in take(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
TypeError: take() takes at most 4 arguments (5 given)
0.262435264634
-
5/21/2018 Estadistica con python I.pdf
25/30
In [131]: # estos son los centroides de los tres grupos:printcodebook
In [133]: # A continuacin, la funcin vq() asigna nmeros de clusters (cdigos del codebook) a las observaciones:
In [134]: code,distance = vq(df.values,codebook)
In [136]: # As obtenemos el cdigo de cada observacincode
In [138]: colores = ['red', 'blue', 'green']c = [colores[i] fori incode]printc
In [139]: plt.scatter(x,y, s=60, c=c)
Ejemplo completo de clustering
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
[[ 1.0667271 1.07991825][ 2.17020602 2.05327779]
[ 3.11882952 2.93226726]]
Out[136]: array([0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2])
['red', 'red', 'red', 'red', 'blue', 'blue', 'blue', 'blue', 'green', 'green', 'green', 'green']
Out[139]:
-
5/21/2018 Estadistica con python I.pdf
26/30
In [148]: !ls ./datos
In [144]: %load_extrmagic
In [149]: %%Rload("./datos/samsungData.rda")write.csv(samsungData,file="./datos/samsungData.csv")
In [150]: !ls ./datos
In [151]: samsungData = pd.read_csv('./datos/samsungData.csv')
In [152]: samsungData.tail()
In [153]: samsungData.shape
In [165]: # Nombres de las 10 primeras columnassamsungData.columns[0:10]
In [168]: # Nombres de las 10 ltimas columnassamsungData.columns[-10:]
In [161]: samsungData = samsungData.drop('Unnamed: 0', axis=1)
foods-2011-10-03.json prueba prueba4.txt samsungData.rdahola prueba2.csv prueba5.txt warningsphoenix.html prueba3.csv prueba.csv
phoenix-tidied.html prueba4.csv prueba.html
foods-2011-10-03.json prueba prueba4.txt samsungData.csvhola prueba2.csv prueba5.txt samsungData.rdaphoenix.html prueba3.csv prueba.csv warnings
phoenix-tidied.html prueba4.csv prueba.html
Out[152]:
Int64Index: 5 entries, 7347 to 7351
Columns: 564 entries, Unnamed: 0 to activity
dtypes: float64(561), int64(2), object(1)
Out[153]: (7352, 564)
Out[165]: Index([u'tBodyAcc-mean()-X', u'tBodyAcc-mean()-Y', u'tBodyAcc-mean()-Z',u'tBodyAcc-std()-X', u'tBodyAcc-std()-Y', u'tBodyAcc-std()-Z', u'tBodyA
cc-mad()-X', u'tBodyAcc-mad()-Y', u'tBodyAcc-mad()-Z', u'tBodyAcc-max()-X'], dtype=object)
Out[168]: Index([u'fBodyBodyGyroJerkMag-kurtosis()', u'angle(tBodyAccMean,gravity)', u'angle(tBodyAccJerkMean),gravityMean)', u'angle(tBodyGyroMean,gravityMean)', u'angle(tBodyGyroJerkMean,gravityMean)', u'angle(X,gravityMean)', u'angle(Y,gravityMean)', u'angle(Z,gravityMean)', u'subject', u'activity'], dtype=object)
-
5/21/2018 Estadistica con python I.pdf
27/30
In [162]: samsungData.columns[0:10]
In [163]: samsungData['activity'].value_counts()
In [178]: # para hacernos una idea de como viene codificado el dataframe# vamos a listar un subconjunto:
samsungData.ix[985:995,[0,1,2,3,4,5,-2,-1]]
Hay una lnea por sujeto y lectura de los accelermetros, y a cada vector de observaciones se asigna una
actividad. A continuacin vamos a ir probando variables del sujeto 1, y viendo si estas variables discriminan
bien entre actividades:
In [205]: # Array de actividadesacts = samsungData['activity'].unique()# secuencia de colores
cols = 'bgrcmy'
Out[162]: Index([u'tBodyAcc-mean()-X', u'tBodyAcc-mean()-Y', u'tBodyAcc-mean()-Z',
u'tBodyAcc-std()-X', u'tBodyAcc-std()-Y', u'tBodyAcc-std()-Z', u'tBodyAcc-mad()-X', u'tBodyAcc-mad()-Y', u'tBodyAcc-mad()-Z', u'tBodyAcc-max()-X'], dtype=object)
Out[163]: laying 1407standing 1374sitting 1286walk 1226walkup 1073walkdown 986dtype: int64
Out[178]:tBodyAcc-
mean()-X
tBodyAcc-
mean()-Y
tBodyAcc-
mean()-Z
tBodyAcc-
std()-X
tBodyAcc-
std()-Y
tBodyAcc-
std()-Z subject
985 0.198992 -0.002455 -0.117281 0.100775 0.355080 -0.266647 5
986 0.158101 -0.040474 -0.134750 0.063741 0.265524 -0.299606 5
987 0.281287 -0.034803 -0.089352 -0.064575 0.314012 -0.280909 5
988 0.418010 -0.016577 -0.153921 -0.047141 0.283657 -0.178543 5
989 0.428925 -0.037568 -0.169470 -0.033747 0.300829 -0.229894 5
990 0.292996 -0.036746 -0.111782 -0.953571 -0.863929 -0.870786 6
991 0.276552 -0.028512 -0.110449 -0.987560 -0.945003 -0.944290 6
992 0.271818 -0.032274 -0.113994 -0.995988 -0.959353 -0.955563 6
993 0.275229 -0.010966 -0.089999 -0.995814 -0.958768 -0.976571 6
994 0.279222 -0.005795 -0.092436 -0.996173 -0.969167 -0.980864 6
995 0.276892 -0.018711 -0.109727 -0.994897 -0.972814 -0.963744 6
-
5/21/2018 Estadistica con python I.pdf
28/30
In [206]: # Crear un diccionario de coloresdic_col = {acts[i]:cols[i] fori inrange(len(acts))}dic_col
In [207]: # Seleccionamos las filas del primer sujetosubj1 = samsungData[samsungData['subject']==1]
# Ahora creamos un objeto "groupby" para agrupar por actividadgrouped = subj1.groupby('activity')
In [212]: #En abcisas vamos a representar los valores de la primera variable# Y en ordenadas el nmero de la observacin (la lectura)
# Siempre referido al sujeto 1
fig, (ax1, ax2) = plt.subplots(1,2, sharey=True)fig.set_size_inches(10, 5)
foract, df ingrouped: 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'# Observacin') ax2.set_xlabel(samsungData.columns[1])
ax2.legend(loc='upper left')
Conclusin: las dos primeras variables no nos permiten discriminar por tipos de actividad
Ahora vamos a probar a hacer un agrupamiento jerrquico basado en las tres primeras columnas, a ver si
esto nos permite separar por grupos con un tipo de actividad
Out[206]: {'laying': 'r',
'sitting': 'g','standing': 'b','walk': 'c','walkdown': 'm',
'walkup': 'y'}
-
5/21/2018 Estadistica con python I.pdf
29/30
In [233]: # Construimos una variable categrica (factor) con las actividades
# Ya que de esta manera actF.labels contendr la actividad# codificada numricamente de 0 a 5actF = pd.Categorical.from_array(subj1['activity'])
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 tamao de la fi
guradendrogram(z, orientation='right', color_threshold=0.2, leaf_label_func=lambdan : 'X' * (actF.labels[n] + 1));fig = plt.gcf()# Get current figurefig.set_size_inches(5,10)# Otra forma de dar el tamao
Vamos a probar ahora con las columnas 9 y 10
-
5/21/2018 Estadistica con python I.pdf
30/30
In [245]: #En abcisas vamos a representar los valores de la primera variable# Y en ordenadas el nmero de la observacin (la lectura)# Siempre referido al sujeto 1
fig, (ax1, ax2) = plt.subplots(1,2, sharey=True)fig.set_size_inches(10, 5)
foract, df ingrouped:
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'# Observacin') ax2.set_xlabel(samsungData.columns[10]) ax2.legend(loc='upper left')
Continuaremos este ejemplo ms adelante una vez hayamos visto el anlisis de componentes principales
(PCA)
In []: