Estadistica con python I.pdf

download Estadistica con python I.pdf

of 30

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