Un introducción al análisis de datos con Python

En la entrada “Algo sobre Python, análisis de datos y machine learning”, comenté en general sobre algunas librerías e instalación de Python, pero no mostré mucho sobre como procesar datos en un sentido amplio y general.

Termina de leer

En esta entrada trato de desarrollar con algunos ejemplos un tono más parecido a lo que uno hace en R project cuando tienen información. Ejemplo, en general cuando se tienen una “tabla” de datos uno revisa ciertos aspectos; si es información que lista para analizar quizás contenga campos sin información (NaN), las variables y el tipo de variables ( categóricas, indicadoras, etc.). Después uno juega con algunos gráficos que ayudan a tener una visión o perspectiva de los datos. Pero hay otro tipo de cosas que uno puede hacer, como “juntar” esa tabla de datos con otra, seleccionar solo ciertas variables, modificar la forma de la tabla para hacer algo más parecido a una tabla pivot,etc.

Este tipo de cosas son en general usuales en R, pero también se pueden hacer en Python( y en Spark), la librería es Pandas. En el sitio correspondiente a la librería se tienen suficiente material y ejemplos para hacer cosas, como seleccionar algunas columnas, seleccionar algunas filas, explorar los Missing Values, hacer operaciones merge, join o concatenación, o por otro lado aplicar la versión local del MapReduce que es Split-Apply-Combine (SAC), etc.

En la página se cuentan con varios manuales breves que pueden ser guías buenas e ilustrativas. La referencia obligada a estudiar o leer para tener un buen acercamiento con este módulo es el libro “Python for Data Analysis”, escrito por el creador del módulo Wes McKinney.

La intención de esta entrada es hacer un recorrido rápido sobre las operaciones básicas, que van desde la carga de datos y la exploración gráfica básica , hasta el procesamiento de los Data.Frame para aplicar técnicas del tipo SAC.

No intento que sea exhaustiva esta entrada, es más una lista de ejemplos breves. Al final de la entrada dejo la liga a un tutorial más amplio ( pero aún así breve) que escribo sobre el uso de Pandas y que dejo alojado en Github.

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Si leíste la entrada hasta aquí, seguro te parecerá raro porqué está marcado buena parte del texto y otro párrafos no. Bueno, después de intentar escribir esta entrada decidí tomarme un poco más en serio el escribir un breve tutorial con ejemplos construidos con datos reales.

Como ya es más o menos escuchado el tema de “datos abiertos” decidí escribir algunos ejemplos de la manipulación de datos con Pandas.

La liga es la siguiente:

https://github.com/dlegor/Tutorial-Pandas-Python

Espero posteriormente remediar lo redactado en esta entrada y terminar el tutorial, pero ya tienen material suficiente para tener un breve pero práctico acercamiento a procesar datos con Python.

—–Pendiente por terminar.

 

 

 

 

Split-Apply-Combine- Parte 3

A terminar el ejemplo!!!

En la entrada Split-Apply-Combine parte 2, mostré unos ejemplos sencillos de como usar librerías de R y de Python para manipular los datos y obtener otro tipo de relaciones tales que de manera directa explorando la información sin transformarla no pueden ser detectadas dichas relaciones.

La relevancia de transformar la información y encontrar nuevas relaciones es parte fundamental para un buen análisis, esto requiere un poco de ensayo y error, de jugar con los datos y el tipo de datos, de buscar conexiones para tratar de descubrir alguna relación. Pero lo descubierto no implica que las “relaciones”  determinan algo relevantes, lo que en teoría uno debe de hacer es validar estos supuesto descubrimientos por medio de alguna técnicas estadística  para probar que la hipótesis o descubrimiento son por lo menos estadísticamente ciertos.

Lo que he compartido en las dos entradas previas(Parte 1 y Parte 2) es en general se puede considerar solo como exploración y diagnóstico, la idea de Split-Apply-Combine( SAC) es dividir , aplicar y combinar los resultados y por medio de esto obtener información que relevante.

El ejemplo en la referencia [1] da una idea de la metodología de manera fácil, por lo cual replico uno de los ejemplo para incentivar a revisar la referencia y observar como se aplica la metodología. El código que uso no es el mismo que comparten en dicho artículo, pero se obtienen los mismo resultados.

Las etapas son las siguientes:

  1. Se cargan los datos y se analiza la muestra de datos para un solo jugador( Split).
  2. Se construye un modelo el cual se aplica a cada uno de los jugadores(Apply).
  3. Se eligen dos elementos obtenidos del modelo para analizar el comportamiento de los datos en general y se muestran algunas gráficas para expresar los resultados (Combine).

Los datos corresponden a la base de datos baseball que se puede obtener desde la librería plyr.

#Split
#Se cargan las librerías
library(dplyr)
library(reshape)
library(plyr)
library(ggplot2)

#Se cargan los datos y se revisan que no cuente con NA
data("baseball")
head("baseball")
sum(is.na("baseball"))

#Se elige solo los datos correspondiente a baberuth

baberuth=filter(baseball,id=="ruthba01")
head(baberuth)
dim(baberuth)
#str(baberuth) se puede usar este comando para explorar que tipo de variables se tienen en los datos.

#Se agregan un par de variables para analizar lso años jugando y el número de carreras por bateos y el número de ocasiones que pasó a batear.

L=mutate(baberuth,cyear=year-min(year)+1,indice=rbi/ab)

#Se analiza la relación entre las dos nuevas variables

ggplot(L,aes(x=cyear,y=indice))+geom_line(col="red")+ggtitle('Relación entre datos')+
 xlab('Índice')+ylab('Ciclo de años')+geom_smooth(method='lm')

SAC_baseball

El código anterior lo que hace es elegir una muestra de datos y analizar la relación entre un par de variables que se construyen de las variables existentes, para ver la información de la descripción de la base se puede consultar por medio del comando ?—nombre de la base—.

La gráfica muestra una relación  y se hace un ajuste lineal como modelo para estudiar dicha relación. Esto no necesariamente es buen buen modelo, pero como ejemplo resulta fácil de entender y de aplicar.

#Apply
#Se construye el modelo 

model<-function(df){lm(rbi/ab~cyear,data=df)}

#Seleccionan los datos que permitan aplicar el modelo
L2=filter(baseball,ab>25)
#Se agregan las variables para toda la base

L3=mutate(L2,cyear=year-min(year)+1,indice=rbi/ab)
#Se aplica el modelo 
bmodels<-dlply(L3,.(id),model)
#Se observan el data.frame obtenido después de aplicar el modelo
head(bmodels)

Lo que se hace en el código anterior es lo siguiente, ya que se definen las nuevas variables y se analiza su relación se procede agregar esas variables para toda la base y se define una función que es el modelo aplicar a todos los datos, posteriormente se elige de la base aquellos elementos que permiten que el modelo se aplique. Si se aplica el modelo a toda la base sin revisar los valores de la variable ab, se obtendrá un error, esto debido al cálculo del modelo sobre los datos.

Se aplica el modelo por medio de la función dlplyr, el “dl” del comando indica que manda un data.frame para obtener una lista.Por último observo como son los datos por medio de head().

La parte de combinar los resultados implica usar algún estadístico para analizar los modelos, en la primera gráfica se observa que no es un buen modelo, entonces haciendo los ajustes lineales se puede extraer la r cuadrada que indica que tan bueno es el modelo de manera descriptiva. Ya que si la r cuadrada es muy alta indicaría que la relación es muy lineal y que el modelo es hasta cierto punto bueno, pero si es baja indica que no lo es.

Por lo tanto lo que hago, siguiendo al artículo o referencia [1], es extraer tanto la  r cuadrada de cada modelo, como la intercepto de la recta. Sabiendo un poco de geometría, se debe de tener en cuanta que la pendiente de la recta está relacionada con la correlación de las dos variables analizadas y por lo tanto con el valor de la r cuadrada.

#Combine

# Se define la función para extraer la R cuadrada de los modelos

rsq<-function(x)summary(x)$r.squared
#Se aplica el modelo a la lista y se regresa un data.frame
bcoef<-ldply(bmodels,function(x)c(coef(x),rcuadrada=rsq(x)))
head(bcoef)
#Se cambian nombres a las columnas
names(bcoef)[2:3]<-c("intercept","slope")
head(bcoef)

#Se revisa el histograma de los datos
ggplot(bcoef,aes(rcuadrada))+geom_histogram(col="red")+ggtitle('Histograma de R cuadradas')+
 xlab('Valores de R cuadrada')+ylab('Conteo')

#Se asigna el valor de las variables a toda la base
baseballcoef<-merge(baseball,bcoef,by="id")
head(baseballcoef)
dim(baseballcoef)

#Grafica 1
d1=qplot(data=baseballcoef,x=slope,y=intercept)+xlim(-0.05,0.05)+ylim(-2,2)
d1+geom_point(alpha=0.05,aes(size=rcuadrada))+ggtitle('Cruce de pendiente vs interceptos')+
 xlab('Pendientes')+ylab('Interceptos')+geom_hline(yintercept=0,col="red")+geom_vline(xintercept=0,col="red")

#Gráfica 2
d2=qplot(data=baseballcoef,x=slope,y=intercept)+xlim(-0.010,0.010)+ylim(-.25,.25)
d2+geom_point(alpha=0.05,aes(size=rcuadrada))+ggtitle('Cruce de pendiente vs interceptos')+
 xlab('Pendientes')+ylab('Interceptos')+geom_hline(yintercept=0,col="red")+geom_vline(xintercept=0,col="red")

Lo que hace todo el código anterior es extraer un estadístico que permita saber si es bueno el modelo, analizar gráficamente los datos. Por último analizar la posible relación gráfica entre los estadístico extraídos. Las gráficas son las siguientes:

Hist_baseball

SAC3SAC3_2

Entonces en resumen lo que se hizo, aun que fue replicar los cálculos del artículo trato de agregar algún modo distinto de obtenerlo con el código. La técnica al final es clara con este ejemplo, cada paso puede requerir más detalle y exploración sobre la información, pero en resumen la primera de estas últimas gráficas muestra que el modelo es malo, lo cual reta a buscar un mejor modelo para analizar los datos y otros estadísticos.

Ejemplo 2

Retomando los ejemplos de los datos de vuelos desde tres aeropuertos cercanos a la ciudad de NY, tenemos que que la base de datos es considerablemente más grande que el ejemplo anterior. Lo que trato de evitar con el ejemplo es hacer confuso como aplicar la técncias de SAC, así que lo que hago en un primer momento es algo similar al ejemplo anterior.

Tomo los datos, reviso el indicador “tailnum” para elegir los aviones que tienen el mismo número en la cola del avión y después analizo un par de variables que no son tan relevantes pero que permiten hacer un modelo sobre los tiempos de retraso al despegar y al arribar. Lo único que cambia es que la regresión o el modelo lineal es múltiple y es un buen modelo, lo cual no es de sorprender ya que si un avión se retrasa al despegar se espera que también se retrase al arribar.

Las etapas son las siguientes:

  1. Se cargan los datos y se analiza la muestra de datos para un solo registro “tailnum”, de hecho elijo el que aparece más ocasiones en los datos (Split).
  2. Se construye un modelo el cual se aplica a cada uno de los registros (Apply).
  3. Se eligen dos elementos obtenidos del modelo para analizar el comportamiento de los datos en general y se muestran algunas gráficas para expresar los resultados (Combine).
#Split

library(nycflights13)
library(plyr)
library(dplyr)
library(reshape2)
library(ggplot2)

data("flights")
dim(flights)
#[1] 336776 16

#missing value
sum(is.na(flights))
#[1] 60593
flights2=na.omit(flights)

head(flights2,10)
str(flights2)
dim(flights2)
#[1] 327346 16

#Seleccionamos el que tiene mayor número de apariciones

sort(summary(factor(flights2$tailnum)),decreasing = TRUE)

N725MQ=filter(flights2,tailnum=="N725MQ")

head(N725MQ)
dim(N725MQ)

#Agrego dos variables
N725MQ_2=mutate(N725MQ,dep_d=dep_delay-min(dep_delay)+1,arr_d=arr_delay-min(arr_delay)+1)

#Gráfica de cruce entre variables por mes
ggplot(data=N725MQ_2,aes(y=dep_d, x=arr_d))+geom_point(aes(colour=factor(month)))+geom_smooth(method='lm')

La gráfica que se obtiene es la siguiente:

fligths3_cruce

La gráfica muestra que existe una relación linea entre las dos variables que se definieron, pero esto además agrego una revisión de como se comportan los datos con respecto a los meses de vuelo y si bien no es claro una relación muestra que el comportamiento no es del todo aleatorio, en ciertos meses se presenta un retraso mayor que en otros. Un modo de ver esto es correr la regresión lineal solo para los datos de este registro de tailnum y revisar si es significativa, en este caso R cuadrada marca un 0.8 lo cual es bastante bueno.

Entonces lo que ahora hago es aplicar este modelo a los datos de toda la tabla.

#Apply
#Definición del modelo
modelo<-function(df){lm(dep_d~arr_d+month,data=df)}

#Procesamiento de toda la base
flight3=mutate(flights2,dep_d=dep_delay-min(dep_delay)+1,arr_d=arr_delay-min(arr_delay)+1)

#Aplicación del modelo
fmodelo<-dlply(flight3,.(tailnum),modelo)
head(fmodelo)
str(fmodelo)

#Extracción del estadístico
rsq<-function(x){summary(x)$r.squared}

fcoef<-ldply(fmodelo,function(x)c(coef(x),rcuadrada=rsq(x)))

#Extracción de datos del modelo
fcoef=ldply(fmodelo,function(x)c(coef(x),rcuadrada=rsq(x)))
head(fcoef)
names(fcoef)[2]=c("Intercepto")

#Histograma del modelo
ggplot(fcoef,aes(rcuadrada))+geom_histogram(col="red")+ggtitle('Histograma de R cuadradas')+
 xlab('Valores de R cuadrada')+ylab('Conteo')

La gráfica que se obtiene es la siguiente:

flights_hist

El histograma muestra que la regresión es un buen modelo para analizar todos los datos, y que se comporta bien la r cuadrada, es decir que es próxima a 1, lo único extraño es el conjunto de valores que tienen un valor pequeño  o cercano a cero, esto indica que debe de revisarse el para algunos registros. Esto de puede hacer de modo fácil usando la función filter().

 Lo último es combinar la información con la tabla original y analizar las relaciones entre los valores estimados del modelo. Estos datos permiten hacer otra exploración de la información y de cierto modo los datos fueron enriquecidos.

#Combine
#Unión de las dos tablas
flightscoef<-merge(flights2,fcoef,by="tailnum")
head(flightscoef)
dim(flightscoef)
str(flightscoef)

#Gráficas de resultados por aeropuerto de origen
ggplot(flightscoef,aes(rcuadrada))+geom_histogram(color="black",aes(fill=origin))+ggtitle('Histograma de R cuadradas')+
 xlab('Valores de R cuadrada')+ylab('Conteo')

#Gráficas de coeficientes

d1=qplot(data=flightscoef,x=month.y,y=Intercepto)
d1+geom_point(alpha=0.05,aes(size=rcuadrada))+ggtitle('Cruce de pendiente vs interceptos')+
 xlab('Pendientes de Meses')+ylab('Interceptos')+geom_hline(yintercept=0,col="red")+geom_vline(xintercept=0,col="red")

d2=qplot(data=flightscoef,x=arr_d,y=Intercepto)
d2+geom_point(alpha=0.05,aes(size=rcuadrada))+ggtitle('Cruce de pendiente vs interceptos')+
 xlab('Pendientes de Meses')+ylab('Interceptos')+geom_hline(yintercept=0,col="red")+geom_vline(xintercept=0,col="red")

Las gráficas que se obtienen son las siguientes:

flights_hist_origin

flights1_082015Flights2_082015

Lo que se observa es que efectivamente el comportamiento del modelo por aeropuerto de origen es similar, lo cual se ve en el histograma con diferentes colores por origen. Las otras dos gráficas muestran la primera la relación entre los coeficientes de la regresión, entre los cuales se aprecia cuales tienen cierto comportamiento, para profundizar en el análisis de estos coeficientes se requiere un poco más de detalle, pero en general la idea de aplicar SAC es también reflejada en este ejemplo.

Ultimo ejemplo.

En la entrada Split-Apply-Combine Parte 2 mostré que los datos podían ser analizados como series de tiempo después de una serie de transformación sobre la información, lo que trato de hacer con el ejemplo es aplicar un modelo de series de tiempo a los datos por medio de la metodología SAC.

Lo primero que hago es procesar la información y explorar solo los datos como series de tiempo de un solo registro de “tailnum”, esto se muestra gráficamente que tienen cierto comportamiento, el registro elegido es el que cuenta con mayor cantidad de datos o líneas en la base, el cual es “N725MQ”.

El código para explorar la información y los datos es el siguiente:

#Ejemplo de Series de tiempo
#Cargo las librerías requeridas
library(nycflights13)
library(plyr)
library(dplyr)
library(reshape2)
library(ggplot2)

#Revisión de los datos

data("flights")
dim(flights)
#[1] 336776 16

#missing value
sum(is.na(flights))
#[1] 60593
flights2=na.omit(flights)

head(flights2,10)
str(flights2)
dim(flights2)
#[1] 327346 16

#Seleccionamos el que tiene mayor número de apariciones
sort(summary(factor(flights2$tailnum,labels=levels)),decreasing = TRUE)

#Elijo el registro con mayor cantidad de líneas es "N725MQ"

N725MQ=filter(flights2,tailnum=="N725MQ")
head(N725MQ)
dim(N725MQ)

N725MQ_1=mutate(N725MQ,fechas=as.Date(paste(month,day,year,sep="/"),"%m/%d/%Y"))

Dat_1<-N725MQ_1%>%
 group_by(fechas,tailnum)%>%
 summarise(dis_m=mean(distance))

head(Dat_1)
qplot(data=Dat_1,x=fechas,y=dis_m,geom=c("line","point"))+geom_point(colour="red")+scale_x_date()+ggtitle('Seríe de N725MQ')

La gráfica que se obtiene es la siguiente:

SAC_timeseries

Estos datos se pueden tratar como una serie de tiempo, burdamente elijo un modelo para esta seria, el método que elijo es  ets (exponential smoothing), la intención es aplicar el modelo y tomar el estadístico RMSE, el cual la raíz de la media de los errores cuadrados y a grandes rasgos representa la desviación estándar entre los valores predichos y los estimados.

El código para aplicar el modelo a esta serie y obtener el RMSE, es el siguiente:

#Código
#Modelo
TS=ts(Dat_1$dis_m)
S=ets(TS)
S1=summary(S)
#El valor de RMSE es el siguente
S1[2]
201.2376
plot(TS, main="Serie de N725MQ para el año 2013",col="blue", ylab="Valores de la serie", xlab="Tiempo")
lines(S$fitted,col="2")

SerieN725MQ_1

Ahora el trabajo es elegir un cierto grupo de valores de tailnum que permitan aplicar el modelo y explorar como se comporta el estadístico y ver el comportamiento de los parámetros alpha y beta del modelo para cada un de los registros elegidos. Entonces se requiere que se transformen los datos, que se seleccionen cierto grupo de datos, se aplica un modelo y se extrae un estadístico para revisar el comportamiento del modelo.

#Transformando los datos
Datos1<-Vuelos1%>%
 group_by(fechas,tailnum)%>%
 summarise(dis_m=mean(distance))

Dato2=melt(Datos1,id=c("fechas","tailnum"))

Datos3=dcast(Datos1,fechas~tailnum)

Datos3[is.na(Datos3)] <- 0

#Eligiendo los tailnum con mayor actividad
Lista<-flights2%>%
 group_by(tailnum)%>%
 summarise(cantidad=n())

Aviones=filter(Lista,cantidad>365)

Lista_av=Aviones$tailnum

Lista_av2=c('fechas',Lista_av)

#Selección
Datos4=subset(Datos3,select=Lista_av2)

#Gráficas del comportamiento de algunos registros
ggplot(Datos4,aes(x=fechas,y=N324JB))+geom_line()
ggplot(Datos4,aes(x=fechas,y=N713MQ))+geom_line()
ggplot(Datos4,aes(x=fechas,y=N722MQ))+geom_line()

Como ejemplo gráfico algunos de los registros para ver su comportamiento en el año.

N324JBN713MQN722MQSe aprecia en los gráficos que el comportamiento es diferente y que es de esperar que el modelo no sea el mejor para todos los registros.

#Todos los datos
Datos5=melt(Datos4,id="fechas")
head(Datos5)
ggplot(Datos5,aes(x=fechas,y=value,color=variable,group=variable))+geom_line()+
 ggtitle('Todos los datos')+
 ylab('Media de las distancia de vuelos')+xlab('Fechas')

El comportamiento de todos los registros es el siguiente:

Todos_tailnum

Se hace notar que el comportamiento de separa en dos bloques, por lo cual es posible que para los vuelos que muestran mayor actividad el modelo sea más adecuado.

#Más transformaciones

#Ultima transformación
Datos6=dcast(Datos5,variable~fechas) 
head(Datos6)
colnames(Datos6)[1]<-'tailnum'
str(Datos6)

#Modelo
modelo<-function(df){ets(as.numeric(df))}

#Aplicación del modelo
Amodels<-dlply(Datos6,.(tailnum),modelo)

#Estadistico
rmse<-function(x){sqrt(x$mse)}

#Extracción del estadistico
Acoef<-ldply(Amodels,function(x)rmse(x))



ggplot(Acoef,aes(x=tailnum,y=V1))+geom_boxplot(col="red")+
 ggtitle("RMSE")+theme(plot.title=element_text(lineheight = 1,face='bold'))+ylab("RMSE")+xlab("TailNum")

Estas última parte del código hace el cierre de la metodología SAC, ya teniendo los datos preparados para aplicar el modelo se define la función que se va aplicar, se extrae el estadístico y se revisan los resultados con algún gráfico para tener identificado como se comportó el modelo.

Considerando que RMSE indica la desviación estándar de los errores del modelo, lo que se desea es que no sea muy grande ya que indica que los errores no están tan centrados. Esto es burdo pero es un modo sencillo de interpretar el gráfico que analizar como se comporta el modelo, el gráfico es el siguiente:

RMSE_ejemploRevisando en los datos, se observa que por ejemplo el vuelo N335AA tiene un comportamiento no muy favorable para el modelo,  haciendo la gráfica del comportamiento en el año se observa lo siguiente:

N335AAPara el cual se ve complicado que el modelo funcione bien, ya que siendo de suavizado exponencial no se favorable su aplicación.

 Espero que la entrada ilustre de manera general como se hace uso de la metodología SAC, si bien fueron tres entradas para explicar su aplicación la intensión es tener varios ejemplos tanto de gráficas exploratorias , como de gráficas no triviales y la aplicación de algún modelo sencillo que permita visualizar la metodología de manera clara.

Referencias:

1.-http://www.jstatsoft.org/v40/i01/paper

 

 

Algo de procesamiento de datos

Algunas herramientas de manipulación de datos

En general la intención de esta categoría es  comentar sobre las técnicas de exploración, pero revisando y diseñando las entradas me di cuenta que dejé de lado una cosa que creo es fundamental, el procesamiento de datos o pre-procesamiento.

Creo que es central el tema, ya que con un poco de suerte uno tienen la información ordenada y mal que bien lista para poderla usar y explorar.

Ejemplo, ingresando a la siguiente liga yahoo uno puede extraer datos de yahoo fincance sobre el el indicador S&P, tiene varios formatos y la información está lista para analizarse, todo se encontrará bien ordenado. Pero no pasa lo mismo si uno quiere analizar algún texto, ejemplo; si uno ingresa la http://www.gutenberg.org puede descargar algún texto en formato HTML, el cual requiere procesarse para posteriormente poder analizarse con técnicas de Procesamiento de Textos o Text Mining, pero peor aún si uno construye un corpus que es un conjunto de textos, procesarlos requiere todo un labor.

Por otro lado, si se tienen la información ordenada lo que uno en ocasiones requiere es ver la relación entre algunas variables o estimar la media o conocer los máximos o mínimos. Para esto se requiere saber como manipular los datos.

 La exploración y construcción de algún modelo según sea el interés u objetivo, requiere de aprender o conocer los datos. Si bien para esto están los procesadores de bases de datos, lo que uno trata con herramientas como R o Python, es hacer uso de otro tipo de algoritmos que posiblemente requieren manipular bases considerablemente grandes antes de implementar el algoritmo.

Tratando de limitar la entrada comentaré sobre algunas librerías para procesamiento de datos en R y sobre el procesamiento de datos en Python. Por último agrego algunos comentarios sobre el procesamiento con Julia.

Librerías en R.

Es posible que existan más librerías que hacen manipulación de datos en R, pero las recomendadas y sobre todo reconocidas en varios cursos como en DataCamp, son reshape2, dplyr y data.table.

Comento sobre las tres y dejo los artículos donde pueden consultar información al respecto en la lista de  referencias.

Reshape2….después de reshape

La librería fue desarrollada por Hadley Wickham, la última versión se llama reshape2 la cual sufrió algunos cambios con respecto a la primera versión, como toda librería actualizada. La utilidad de la librería la trato de explicar con los ejemplos y estos son tomados del artículo [1].

Los datos para los ejemplos se cargan dentro de la misma librería. Este código lo corrí en RStudio.

#Cargamos las librerías para el ejemplo

library(reshape2)
library(ggplot2)

#En caso de que se quiera ver la información de la libreria se puede poner el comando
#library(help='reshape2')

#Primer ejemplo
data("smiths")

#Exploramos los datos

head(smiths)
dim(smiths)

#Se observa que solo cuenta con dos filas y 5 columnas
#La primera función importante "melt"
#para ver información de la función se puede usar
#?melt o help(melt)

#Se definen los id y las medidas

melt(smiths,id=c("subjects","time"),measured=c("age","weight","height")
#R regresa algo como esto:
# subject time variable value
#1 John Smith 1 age 33.00
#2 Mary Smith 1 age NA
#3 John Smith 1 weight 90.00
#4 Mary Smith 1 weight NA
#5 John Smith 1 height 1.87
#6 Mary Smith 1 height 1.54

#Obtenemos el mismo resultado de la siguiente forma

melt(smiths,id=1:2,measured=c("age","weight","height")

#Se hace la misma petición pero evitando los datos NA

melt(smths,id=1:2,measured=c("age","weight","height"),na.rm=TRUE)

# subject time variable value
#1 John Smith 1 age 33.00
#2 John Smith 1 weight 90.00
#3 John Smith 1 height 1.87
#4 Mary Smith 1 height 1.54

La función melt lo que hace es elegir de la pequeña tabla de datos las variables que considera id y el resto las considera como variables sobre las cuales muestra sus valores para cada id. Si se solicita la dimensión o tamaño de la tabla al usar melt se observa que hay un cambio en la estructura de la tabla. Es decir, en una petición por melt, pedir dim(melt(….)) deja ver que se cambio la forma de la tabla, de allí el origen del nombre.

La razón de su utilidad es que se pueden elegir varias variables que se desean explorar como una sola, en este caso subject y time y para cada una de sus posibles combinaciones se observan los valores de las variables age, weight y height.

Esto a primera vista no tienen relevancia o no se aprecia, pero con una tabla de datos poder modificar su estructura facilida un  rápido el análisis tanto gráfico como exploratorio. En el último ejemplo se usa una base de tamaño mayor. Pero antes comento sobre otra función.

#Función cast
Se observa a forma orginal del data.frame smiths

# subject time age weight height
#1 John Smith 1 33 90 1.87
#2 Mary Smith 1 NA NA 1.54

#Se construye una nuevo data.frame con la función melt

smithsm=melt(smiths,id=1:2,measured=C("age","weight","height"),na.rm = TRUE,value.name="Valores")

#Se observa el data.frame construido

smithsm 

#subject time variable value
#1 John Smith 1 age 33.00
#2 John Smith 1 weight 90.00
#3 John Smith 1 height 1.87
#4 Mary Smith 1 height 1.54

dcast(smithm,subject+time~variable)
#Se recupera el data.frame orgianal
 subject time age weight height
1 John Smith 1 33 90 1.87
2 Mary Smith 1 NA NA 1.54

Lo que se observa del código anterior es que se recupera el arreglo original, pero no solo eso hace la función dcast. Con algo de cuidado se observa que dentro de la función se ingresó una expresión Col1+Col2~Fila1+Fila2+….+Filan=variable.

Esta expresión indica la relación entre las columnas y las filas de los datos, que es lo que mostrará esta función. Se puede agregar un elemento más a la función dcast y hace parecer que melt y esta función funcionan de manera inversa. El siguiente ejemplo muestra como usarla para estimar cierto valores.

Para el ejemplo hice uso de una base que está en la librería reshape2, french_fries.

#Cargamos los datos french_fries 
data(french_fries)
ffm<-melt(french_fries,id=1:4,na.rm = TRUE)
#Se eligen solo los datos que no contienen NA
#Se explora la información
head(ffm)
dim(ffm)
#Se calcula con la función cast la media de cada variable, en este caso los valores de variable son:potato,buttery,grassy,rancid y painty

dcast(ffm,rep~variable,mean)
# Se obtiene una table como la siguiente:
# rep potato buttery grassy rancid painty
#1 1 6.956196 1.863663 0.5752161 3.916427 2.361383
#2 2 6.948851 1.784195 0.7528736 3.788218 2.682133

dcast(ffm,.~variable,mean)
# . potato buttery grassy rancid painty
#1 . 6.952518 1.823699 0.6641727 3.85223 2.521758

Lo que hace el código anterior es primero cargar los datos, después modificar sus estructura original para obtener una tabla con las primeras 4 variables como id, esto mediante la función melt. Usando la función dcast, se estima primero desde ffm la relación entre rep y las variables, se calcula su media. En la segunda petición de la función dcast se estima la media en general de las variables, sin separarse por rep como en el primer ejemplo.

El último ejemplo es equivalente al que se muestra en las referencias [1,2].

#Caso de estudio de la base de datos french_fries

data(french_fries)
dim(french_fries)
#[1] 696   9

#Se modifica la estructura de los datos por medio de melt
ffm<-melt(french_fries,id=1:4,na.rm=TRUE)
head(ffm)
# time treatment subject rep variable value
#1 1 1 3 1 potato 2.9
#2 1 1 3 2 potato 14.0
#3 1 1 10 1 potato 11.0
#4 1 1 10 2 potato 9.9
#5 1 1 15 1 potato 1.2
#6 1 1 15 2 potato 8.8

dim(ffm)
#[1] 3471    6

#Se revisan los valores de subject y de time
summary(ffm$time)
# 1 2 3 4 5 6 7 8 9 10 
#360 360 360 360 355 360 359 357 300 300 
summary(ffm$subject)
# 3 10 15 16 19 31 51 52 63 78 79 86 
#270 300 295 299 300 270 300 300 300 300 267 270

#Se hace un cruce entre subject y time para determinar analizar entre la pareja de datos entre los cuales no se tienen información

#Se agregan inicialmente los margenes y en el segundo comando no.
dcast(ffm,subject~time,length,margins=T)
dcast(ffm,subject~time,length)

#Se pueden analizar los valores máximos de cada una de las variables por medio de dcast

dcast(ffm,variable~.,max)

#Construye la gráfica de los valores de las variables
library(ggplot2)
qplot(value,data=ffm,geom="histogram",facets=.~variable,bindwidth=1,main="Histogramas de las variables")

La gráfica que se obtienen es la siguiente:

Histo_ejem_da

La idea general del ejemplo anterior es, construir un data.frame , explorar el comportamiento de los campos sin valor entre dos variables y revisar sus valores máximos. Por último construir una herramienta gráfica, en este caso un histograma; para revisar el comportamiento de las variables. En las referencias se explican más detalles sobre el ejemplo.

La librería reshape2 cuenta con más funciones, sobre las cuales no menciono nada, pero melt y cast son las más destacadas. Para conocer como usar el resto de funciones se puede revisar el manual de uso, referencia[3].

Librería dplyr…antes plyr

Esta librería también fue diseñada por Hadley Wickham, es fundamental debido a que los data.frame son usados como objetos y en general se usa para grandes tablas de datos.

La importancia de este paquete está ligada a la metodología de trabajo “split-apply-combine”, que fue planteada como una metodología similar a mapReduce que fue la solución de manipulación y procesamiento de grandes volúmenes de datos en Google, sobre este tema se puede revisar la referencia [4,5].

Para ser breve comparto un ejemplo publicado en parte en  [6] y trato de comentar de modo breve lo que se hace con esta librería.

Tiene alta relevancia con el procesamiento de datos, por lo cual invito a que se consulte en otros blog con algún tutorial amplio o en algunas de las referencias que dejo.

Cuando se manejan datos uno espera dos cosas, que sea rápido y que sea intuitivo, es decir; que sea fácil para uno pueda recordar los nombres de algunas funciones o la lógica al programar con los comandos. Para replicar el código se requiere una librería hflights que contiene solo una base considerablemente grande para mostrar como se usan las funciones principales de dplyr, o en su defecto se puede usar la librería nycflights13.  Este código lo corrí en RStudio.

#Se se cargan las librerías.

library(dplyr)
library(hflights)

#Cargamos los datos del ejemplo
#Se exploran el tipo de datos y las dimensiones de la tabla.
data(hflights)
head(hflights)
dim(hflights)
#[1] 227496 21

#Data frame local, mediante la función tbl_df()

flights<-tbl_df(hflights)
flights

#Para ver más registros de los dados por default 

print(flights,n=15)

#Convertir en un data frame normal y ver toda la información de manera normal en R

data.frame(head(flights))

###################################################
#Uso de la función filter()

#Método clásico en R
#Eligiendo vuelos de Enero 1

flights[flights$Month==1 & flights$DayofMonth==1,]

#Usando filter para elegir valores del dataframe

filter(flights,Month==1,DayofMonth==1)

#Usando filter y la pipe para condiciones "or"

filter(flights,UniqueCarrier=="AA"|UniqueCarrier=="UA")
#Uso del operador %in%

filter(flights,UniqueCarrier %in% c("AA","UA"))

###################################################
#Función slice
slice(flights,1:13)

###################################################
#Función arrange()
arrange(flights,Year,Month,DayofMonth)
arrange(flights,desc(FlightNum))

###################################################
#Selección de tres columnas
#Método clásico
flights[,c("DepTime","ArrTime","FlightNum")]
#Por medio de dplyr
select(flights,DepTime,ArrTime, FlightNum)

#Otras opciones para seleccinoar
select(flights, Year:DayofMonth,contains("Taxi"),contains("Delay"))

#Asignando títulos a los valores de algunas columnas
select(flights,Mes=Month,Vuelo=FlightNum)

El código anterior, si uno va revisando las salidas en R no resulta nada extraño, pero se pueden observar ciertas comodidades al seleccionar o al filtrar la información, que al hacerlo de manera normal en R resultaría más engorroso.

La siguiente parte del código se hace uso de comandos u operadores propios de la librería.

#Usos de operadores
#Anidación

#Método 1-por filtro
filter(select(flights, UniqueCarrier, DepDelay), DepDelay > 60)

#Método 2-por cadena
flights%>%
 select(UniqueCarrier, DepDelay)%>% 
 filter(DepDelay > 60)

#Distancia Euclideana entre dos vectores

x1<-1:5;x2<-2:6
sqrt(sum((x1-x2)^2))

#Método de cadena para para la distancia Euclideana
(x1-x2)^2%>%sum()%>%sqrt()

##################################################
#Reordernar filas-arrange
#Método estándas en R

flights[order(flights$DepDelay),c("UniqueCarrier","DepDelay")]

#Método en dplyr

flights%>%
 select(UniqueCarrier,DepDelay)%>%
 arrange(DepDelay)

#Método en dplyr en orden descendente

flights%>%
 select(UniqueCarrier,DepDelay)%>%
 arrange(desc(DepDelay))

####################################################
#Mutate
#Creando nuevas variables en los datos
#Método clásico por R

flights$Speed<-flights$Distance/flights$AirTime*60
#Visualización de la nueva variable
flights[,c("Distance","AirTime","Speed")]

#Método 2-Aproximación por dplyr

flights%>%
 select(Distance,AirTime)%>%
 mutate(Speed=Distance/AirTime*60)

flights<-flights%>%mutate(speed=Distance/AirTime*60)

####################################################
#summarise: Reduce variables a valores

#Método estándar en R

head(with(flights, tapply(ArrDelay, Dest, mean, na.rm=TRUE)))
head(aggregate(ArrDelay ~ Dest, flights, mean))

#Método por dplyr

flights %>%
 group_by(Dest) %>%
 summarise(avg_delay = mean(ArrDelay, na.rm=TRUE))

#Se calcula el porcentaje de vuelos cancelados o desviados para cada aerolínea

flights %>%
 group_by(UniqueCarrier) %>%
 summarise_each(funs(mean), Cancelled, Diverted)

Se observa que los operadores permiten tener mejor legibilidad sobre las operaciones pedidas en el data.frame. Por otro lado al contar con nombres intuitivos permite que sea claro al leer el código.

Por último, solo agrego un ejemplo de la referencia [6] de construir subconjuntos y graficar el comportamiento medio de retrasos.

#Procesamiento y gráfica de datos procesados
#Cargamos las librerías necesarias

library(ggplot2)

by_tailnum <- group_by(flights, TailNum)
delay <- summarise(by_tailnum,
 count = n(),
 dist = mean(Distance, na.rm = TRUE),
 delay = mean(ArrDelay, na.rm = TRUE))
delay <- filter(delay, count > 20, dist < 2000)

#Se visualiza el data.frame

delay
dim(delay)

#Distancia media por vuelo

ggplot(delay, aes(dist,delay)) +
 geom_point(aes(size = count), alpha = 1/2,colour='purple') +
 geom_smooth() +ggtitle("Variación de los retrasos contra distancia")+xlab("Distancia")+ylab("Retraso")


La gráfica que se obtiene es la siguiente:

Retrasos_vuelos

 

A primera vista no parece del todo relevante la librería, pero algunas de las cosas que no comento es la conexión con bases de datos, esto permite hacer un análisis con herramientas más ricas de estadística y mejores gráficas propias de R, que las que cuenta un gestos de bases de datos.

Al final, cuando se hace un análisis de datos dos piezas son importantes, el enfoque de la investigación que se realice y las herramientas con las cuales se haga. En este caso, explotar el uso de esta librería dependerá del proyecto que se aborde.

Nota: Para procesar algunas tablas también se puede hacer mediante la librería plyr, la cual es un poco más lenta para tablas grandes pero es igual de amigable que dplyr.

Librería data.table

La librería es de años recientes y poco a poco gana popularidad, se ha mejorado para que sea aún más rápida. Prácticamente sus uso es para procesar datos en R. En buena medida la sintaxis es similar a SQL.

En un base como las que se encuentran en las librerías de R no se notará su utilidad, pero en particular para bases grandes permite hacer manipulación de los datos. Existen varias comparaciones en cuanto al rendimiento contra tiempo al comparar  operaciones similares entre dplyr y data.table, la ventaja de la primera es la facilidad de operar con sus funciones y la segunda resulta ser más eficiente ante volúmenes considerablemente muy grandes.

Solo comento algo breve sobre la creación de tablas en esta librería, la definición de key’s y un poco sobre la agrupación. Se puede ver más detalles en las referencias [7,8]

#Código de data.table
#Se carga la librería

library(data.table)

#Se compara la creación de un data.frame y una tabla 
DF<-data.frame(x=c("b","b","b","a","a"),v=rnorm(5))
DF

class(DF)

#Generado con data.frame de data.table

DT<-data.table(x=c("b","b","b","a","a"),v=rnorm(5))

DT
class(DT)

#Importan datos de  R project

data(cars)
head(cars)

#Se transforman a una data.table

CARS=data.table(cars)
CARS

#La observación es sobre el indicador MB
#Muestra las tablas creadas con data.table
tables()

#Se se pueden aplicar las funciones estándar sobre el data.table

sapply(DT,class)


El código anterior muestra solo como crear tablas con data.table, al observarlas resultan prácticamente iguales a un data.frame estándar y heredas el tipo de funcionalidades o aplicaciones de funciones comunes en R, como sapply.

#Key en data.table

#Se usa DT del código pasada

setkey(DT,x)
DT

#Se observa en tables() que ahora key tienen "x" respecto a DT

#Ejemplo para seleccionar filas
DT[2,]
DT[x=='b',]
#Despues de definir la key se tienen
DT["b",]

Las key puedes ser definidas por varias columnas, al observar las tablas definidas en data.table resultan tener comportamientos similares a los data.frame normales.

Un modo de comparar los procesos normales de R con respecto a los procesos de data.table es comparando los tiempos requeridos para seleccionar partes de una tabla de tamaño, la tabla contendrá 10 millones de filas y 3 columnas.

El siguiente código son solo 3 ejemplos comparativos del tiempo que requiere R y del tiempo que se requiere en data.table para seleccionar o procesar la misma muestra de datos.

#Ejemplos comparativos

#Comparación de busqueda vector scan y binary search

grpsize = ceiling(1e7/26^2)
#Valor
grpsize

#Definición y tiempo de creación d eun data.frame
tt=system.time( DF <- data.frame(
 x=rep(LETTERS,each=26*grpsize),
 y=rep(letters,each=grpsize),
 v=runif(grpsize*26^2),
 stringsAsFactors=FALSE))
#Se revisan las propiedades generales del data.frame
head(DF)
tail(DF)
dim(DF)

tt=system.time(ans1 <- DF[DF$x=="R" & DF$y=="h",]) # 'vector scan'
tt
#Se revisan los datos obtenidos de la selección de valores
head(ans1)
tail(ans1)
dim(ans1)

#Se crea una data.table
DT=as.data.table(DF)
system.time(setkey(DT,x,y))

ss=system.time(ans2 <- DT[list("R","h")])
ss
head(ans2)
tail(ans2)
dim(ans2)

############################
#Otro ejemplo de velocidad entre R y data.table

#Por data.table
system.time(ans1 <- DT[x=="R" & y=="h",])

#Por R 
system.time(ans2 <- DF[DF$x=="R" & DF$y=="h",])

#Validamos que son la misma tabla
mapply(identical,ans1,ans2)

#########################################
#Ejemplo de aplicación de una función sobre las columnas

#Por medio de R
ttt=system.time(tt <- tapply(DT$v,DT$x,sum)); ttt

head(tt)

#Por medio de data.table
sss=system.time(ss <- DT[,sum(v),by=x]); sss

head(ss)

Los resultados que se obtendrán al replicar al código dan una idea de las mejoras que se obtienen al manipular datos con data.table, pero hay recientes estudios donde se compara con dplyr y pandas( de Python). Pero aún así se está mejorando parte de los algoritmos para que sea aún más eficiente. Otra opción es revisar los ejemplos que cuenta la librería , basta con poner en R el comando example(data.table).

Un ejemplo de las ventajas se puede ver en la siguiente liga:

http://stackoverflow.com/questions/11054208/lapply-and-do-call-running-very-slowly

Espero las 3 librerías den una idea en general de lo que se puede hacer en R para procesar datos, unos cursos breves pero que dan una idea global se encuentran en DataCamp, de los cuales la plataforma permite realizar algunos de manera libre y otros tienen costo.

Pandas-Python

La librería para realizar análisis de datos en Python es Pandas, la cual en casi todas las distribuciones de paquetes de librerías o módulos, como Anaconda; viene por default.

Existe mucha referencia respecto al manejo de dicho módulo. Los objetos principales son Series y DataFrame, los cuales son nombres similares a los usados en R project. 

El módulo fue creado por Wes McKinney y la documentación, casos de estudio y todo lo relacionado con pandas se puede consultar en la referencia[9], la cual es sumamente amplia y cuanta con ligas a otras referencias de manuales breves, ejemplos de uso y actualizaciones. El texto clásico y base para aprender sobre este módulo fue escrito por el mismo Wes, es la referencia [10]. Por supuesto es altamente recomendable y los datos para realizar los ejemplos, se encuentran en el repositorio:

https://github.com/pydata/pydata-book

Para el uso del código siguiente considero que se tiene instalado Python 2.7.9 y de preferencia con el paquete de módulos de Anaconda.

El ejemplo para verificar que funciona adecuadamente la el conjunto de módulos con panda, se corre el siguiente código en ipython.

#Prueba 
%pylab
plot(arange(10))

 El código debe de arrojar la siguiente imagen.

Pandas_1

Lo que se hizo fue probar que %pylab, las librerías básicas de desarrollo en ipython se encuentran funcionando. Los módulos base son numpy, matplotlib y pandas.

En los ejemplos solo muestra el uso de pandas para manipulación de datos, con la finalidad de mostrar ejemplos similares a los de R project. En el código de ejemplo considero en general la estructura de datos DataFrame y solo al final doy un breve ejemplo del uso de la estructura Series.

Creación de DataFrame y manipulación básicas.

#Uso de Pandas
#Considerando que se inicio ipython 

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

from pandas import DataFrame

#Se definen datos para creas un DataFrame

data={'Estado':['Jalisco','Sonora','Guanajuato',Veracruz'],'Población':['7838010','2892464','5769524','7985893'],'clave':['09','13','14','23']}

Estados=DataFrame(data)

En Ipython se obtendrá una tabla de datos, sobre la cual se puede manipular la columnas, las filas, agregar nuevas columnas y filas. Si se desea conocer aspectos básicos o métodos que  la estructura de datos DataFrame tienen por default, se puede hacer lo siguiente para conocerlos:

#Datos
Estados.<tabs>

Se presentará una lista de todos los métodos disponibles, ejemplo:

#Métodos
Estado.shape
#Dará el número de columnas y filas que tienen el DataFrame

Estado.head()
#Mostrará solo la cabecera, es decir; una muestra de los primeros 4 registros o filas del DataFrame

Estado.describe()
#En caso de tener una tabla con muchos datos, da un resumen estadístico de la información 

#Si se desea sabes para que sirve cierto método se hace uso de los siguiente.
help(Estados.*)
#Donde en lugar de * se pone el método que se desea conocer

Varios aspectos no menciono, pero en caso de no estar familiarizado con estructuras de datos, recomiendo la referencia [11]. Lo que se oculta al construir el DataFrame por este método es que se asigna data={}, estos paréntesis indican que es un diccionario y [] indica que es una lista.

En R project se hace uso de ciertas librerías para manipular los datos y poder procesarlos de mejor manera, como reshape o dplyr, en python todas esa operaciones se hacen solo con pandas.

Más aún, una postura ante el análisis de datos es la metodología “Split-Apply-Combine”, la cual fue descrita y ejemplificada por Hadley Wickham en la referencia [12]. Esta metodología fue considerada por Wes para el desarrollo de algunos aspectos de pandas, sobre todo en este tema comparto una entrada en esta categoría.

Ejemplo es sencillo y solo muestro algunas operaciones o procesos simples, para mayor detalle y sobre todo para revisar ejemplos de como hacer usos de pandas se puede consultar en la referencia [9].

En el siguiente código se extraen datos desde yahoo finance de los indicadores AAPL e IBM. Se obtiene  un DataFrame de datos, los cuales para mostrar algunas cosas básicas se agregan algunas columnas, de piden algunos datos básicos para explorar la información y se utilizan los dos DataFrame solo para mostrar una operación simple de “Muchos a Muchos”.Se hacen algunas operaciones para agrupar y transformar los datos y por ultimo una gráfica simple sobre el comportamiento de los cierres de los dos indicadores.

#Ejemplo Pandas
#Se cargan las librerias necesarias

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from pandas import DataFrame
import pandas.io.data
import datetime

#Se cargan datos desde yahoo para AAPL y IBM
aapl=pd.io.data.get_data_yahoo('AAPL',start=datetime.datetime(2010,1,1),end=datetime.datetme(2015,1,1))
ibm=pd.io.data.get_data_yahoo('IBM',start=datetime.datetime(2010,1,1),end=datetime.datetme(2015,1,1))
 
#Se exploran los datos, aspectos básicos solo para aapl

type(aapl)
aapl.describe()
aapl.columns
aapl.shape
aapl.head()

#Las dimensiones de los datos

aapl.shape
ibm.shape

Un podo de Missing Values.

#Ejemplo Pandas
#Para trabajar con los Missin Value se toman datos de aapl

aapl_Close=aapl.Close
type(aapl_Close)
#Se oservará que es una estructura de datos serie
#Se toman 200 enteros de entre 0 y 1258 como ejemplo de Missing Value

ind=np.random.randint(1258,size=(200))
aapl_Close[ind]=np.nan

#Para identificar que se cuentan con Missin Value
aapl_Close.isnull()
aapl_Close[aapl_Close.isnull()]
aapl_Close[aapl_Close.notnull()]

#Para elegir solo los datos sin nan
aapl_Close.dropna()
#Para asigar algun valor a los nan, ejemplo se asigna el valor cero "0"
aapl_Close.fillna(0)

Algunas operaciones como la librería Reshape en R project.

#Ejemplo Pandas
#Se define otra columna para elegir el indice como columna

aapl['ind']=aapl.index 

#Se define un nuevo DataFrame por medio de melt

df=pn.melt(aapl,id_vars=['ind'])
df.head()
#Se modifica la estructura de los datos
#Como ejemplo usa df para construir una tabla pivot

pivoted=df.pivot('ind','variables','value')

pivot.head()
#Tienen la misma estructura de los datos originales appl

Ejemplos simple de muchos a muchos y agrupación de los datos.

#Ejemplo Pandas
ibm['index']=ibm.index 

df1=pd.merge(aapl,ibm,left_on='ind',right_on='index',suffixes=('_aapl','_ibm'))

df1.head()
df1.shape
#Se obtienen una tabla con todos los datos de los dos indicadores

#####group by######

#df que proviene de melt
df2=df.groupby('variable')

#Se genera un DataFrame con estructura distinta al origina, el cual muestra agrupamientos por los valores de "variable"
df2.head()

#Algunas funciones sobre el DataFrame agrupado

df2.agg([np.max,np.min,np.mean,np.std])

#Ejemplo de groupby and transform

#Se contruye una Series de los datos de AAPL
aapl.head()
ts=aapl.Open

#Se revisa el tipo de datos y la forma
type(ts)
ts.head()

kye=lambda x:x.year
zscore:lambda x:(x-x.mean())/x.std()

#Caso 1

ts_trans=ts.groupby(key).transform(zscore)

TS_grp=ts_trans.groupby(key)
TS_grp.mean()
TS_grp.std()

#Caso 2

grp=ts.groupby(key)
grp.mean()
grp.std()

#Gráfica de los datos de cierre de los dos inficadores

Indicadores=DataFrame({'AAPL_Close':df1.Close_aapl,'IBM_Close':df1.Close_ibm})
Indicadores.plot()
plt.show()

La gráfica que se obtiene es la siguiente:

Pandas_2

Espero que con este sencillo ejemplo se aprecie que las herramientas de Python para hacer data analysis son bastante buenas, rápidas y dentro de Ipython se tienen prácticamente un entorno de desarrollo solo basta agregarle un block de notas para escribir el código. En la referencia [9] se pueden consultar todos los detalles sobre pandas, muchas cosas al respecto no las menciono pero creo que el mejor lugar para aprender es allí.

Data.Frame-Julia

PENDIENTE DE TERMINAR

 

Tutoriales:

1.-https://www.youtube.com/watch?v=8SGif63VW6E

2.-https://www.youtube.com/watch?v=qLrdYhizEMg

3.-https://www.youtube.com/watch?v=MvH1eTdsekA

Referencias:

1.-http://www.jstatsoft.org/v21/i12/paper

2.-http://had.co.nz/thesis/practical-tools-hadley-wickham.pdf

3.-http://cran.r-project.org/web/packages/reshape2/reshape2.pdf

4.-http://www.jstatsoft.org/v40/i01/paper

5.-http://static.googleusercontent.com/media/research.google.com/es//archive/mapreduce-osdi04.pdf

6.http://cran.rstudio.com/web/packages/dplyr/vignettes/introduction.html

7.-http://cran.r-project.org/web/packages/data.table/vignettes/datatable-intro.pdf

8.-http://blog.yhathq.com/posts/fast-summary-statistics-with-data-dot-table.html

9.-http://pandas.pydata.org/pandas-docs/stable/index.html

10.-http://shop.oreilly.com/product/0636920023784.do

11.-http://interactivepython.org/runestone/static/pythonds/index.html

Algo sobre Python, análisis de datos y machine learning.

Sobre Python

Python es un lenguaje de programación interpretado multiparadigma, es decir; soporta hacer programación orientada a objetos y programación imperativa. Su creador fue Guido Van Rossum y debido a que es de código libre la comunidad de desarrolladores han creado librerías o módulos para hacer casi cualquier cosa.

En general la gente que hace análisis de datos o estadística conoce bien R project, SAS o SPSS. Pero pocos se han acercado a Python y sus librerías para análisis de datos, las ventajas pueden ser cuestionables con respecto a software que específicamente fueron diseñados con una perspectiva estadística, pero sin duda la potencia y calidad de librerías es muy buena. Principalmente para hacer uso de algoritmos de Machine Learning las librerías en Python son mejores que las de R project, sobre todo las técnicas de Deep Learning.

Quizás el mejor candidato para comparar el uso de Python en el análisis de datos es R project, por ser software libre y ser actualmente de alta demanda y atracción en la ciencia de datos. Sin embargo, Python siendo realmente un lenguaje de programación, no como R project, no se limita a ser usado  solamente para analizar datos, sino bien puede ser parte de un sistema o para desarrollar un proyecto completo. 

En caso de que resulte complicado hacer implementación de alguna técnica estadística en Python, se puede enviar un Script a R o manipular los datos desde R y extraerlos a Python por medio de la librería rpy2.

Yo siempre recomiendo para aprender a programar Python, por cosas muy sencillas, es fácil de aprender, fácil de leer y cuenta con librerías para hacer de todo. La curva de aprendizaje es muy corta y en muy poco tiempo uno puede estar programando cosas no tan triviales.

En caso de que se use Windows como sistema operativo, que la mayoría lo usa; se debe de instalar y revisar como hacer instalación de módulos, es bastante fácil y en general se hace desde la consola del sistema con el módulo pip. Si se usa Linux, ya no se tienen ningún problema, está por default, solo basta abrir la terminal del sistema para probarlo.

La mejor referencias para revisar información sobre python, tanto para instalar y conocer el lenguaje, es su página oficial:

https://www.python.org/

Para aprender desde cero a programar en este lenguaje existen muchas páginas y libros, pero creo que solo con ejemplos y ejercicios se aprende, recomiendo seguir y revisar el siguiente libro online:

http://learnpythonthehardway.org/book/

Comentario: cada ocasión que pongo un [] con un número me refiero al número de la lista de referencias.

Sobre Machine Learning y data analysis en Python

Considerando que se tiene instalado Python, las librerías necesarias para hacer los ejemplos que comentaré en las entradas de esta categoría son:

  1. Numpy
  2. SciPy
  3. Matplotlib
  4. Pandas
  5. mlpy
  6. scikit-learn
  7. Pybrain
  8. IPython
  9. NLTK

Por supuesto que hay más librerías necesarias, pero las comento conforme se haga uso de ellas.

Algunas de las convenciones que se hace al programar con las anteriores librerías, sobre todo con Numpy, SciPy , Pandas y Matplotlib, son las siguientes:

#Convenciones en los programas para hacer uso de ciertas librerías
import numpy as np
import pandas as pd
import scipy as sp
import matplotlib.pyplot as plt

 Lo único que dice el código anterior es que se hace uso de nombres cortos y que ahora son estándar en los programas que requieren estas librerías.

Suponiendo que ya se tiene instalado python y las librerías, uno puede revisar en la documentación del lenguaje en la página para ver como se hace uso con: números, variables boolenas, cadenas, listas, diccionarios, loops, tuplas, conjuntos, funciones y clases.

Principalmente el manejo de listas y diccionarios es de uso frecuente al analizar datos, ya que en general se usan para implementar algoritmos sobre un conjunto de datos, y cada uno de estas estructuras de datos tienen sus operaciones o métodos.

Si haz leído hasta este punto y te desanima un poco el aprender a instalar cosas, revisar tanta documentación para solo hacer uso de un software. Bueno, una opción es instalar un paquete con todas la librerías más usadas. Pensando en que mucha gente usa Windows y que la gente que usa Mac o Linux tienen familiaridad con instalación de software, entonces explico cuales son las opciones que conozco.

Las opciones son variadas y depende de las preferencias:

1.-Anaconda.

2.-WinonPyth

3.-Conopy

Cada una de estas instalaciones contiene todas la librerías que uso en los ejemplos, con excepción de pybrain y mlpy. Basta con seguir las instrucciones de instalación que son cosa de dar “click”.

Yo recomiendo Anaconda, es la que he estado usando recientemente y creo que está bien en general. Estos paquetes contienen más herramientas de las que menciono en la entrada, se puede revisar dependiendo del interés de cada uno para qué sirve el resto de librerías.

Un poco de NumPy, SciPy y Matplotlib

En el resto de la entrada trataré de explicar algunas operaciones y usos de las librerías Numpy, Scipy y Matplotlib.

Prácticamente son la base para muchas librerías, Numpy permite manipular arreglos o matrices de datos, si se tiene un poco de conocimiento de álgebra lineal resultará natural conocer las operaciones y funciones de dicha librería. Si no se cuenta con conocimiento de álgebra lineal, recomiendo revisar cualquier texto que prefieran ya que el perfil del texto va desde muy abstracto hasta muy aplicado y depende de la formación e interes de cada persona.

Pero es altamente recomendable revisar conceptos de estos temas lo mejor posible, ya que las matrices son el centro de muchos algoritmos de Machine Learning a todos los niveles.

SciPy, concentra varios procesos, algoritmos o técnicas de manipulación numérica; esto va desde el cálculo de la transformada rápida de Fourier, optimización, procesamiento de señales e imágenes.

Si nunca haz escuchado cosas de estos temas, no te desesperes ni mucho menos tienes que saber todo sobre eso, se aprende con la práctica y la formación, hay gente con carreras completas en ingeniería que no entendió la relevancia del análisis de Fourier  u optimización en sus cursos. En buena medida depende del problema que se aborde para hacer uso de alguna herramienta de Scipy.

Por último Matplotlib, es un módulo para gráficar, existe otro módulo para realizar gráficas que es actualmente muy usado, ggplot2. Este último es muy popular en la comunidad de usuarios de R project pero existe también la versión del módulo en Python y depende la preferencia en cuanto al tipo de gráficos al elegir entre Matplotlib o ggplot2.

El nivel de gráficos es bastante bueno y en ocasiones es tan importante hacer una buena gráfica ya que esto clarifica lo que se hace en el análisis de datos o como se presentan los resultados.

En los últimos años de han desarrollado muchos proyectos de visualización de datos y es prácticamente un campo de investigación, ya que al analizar muchos datos es fundamental tener un modo agradable de visualizar lo resultados de los análisis o investigaciones, de modo tal que sea interactivo e informativo [1].

¿Cómo correr el código en sus computadoras?

Los ejemplos los corrí en una sistema Windows con una versión del sistema 8.1 y con la versión de Python 2.7.9, lamento no comentar respecto a como correrlos en Linux, pero es mucho más simple ya que solo se debe de agregar la ruta del directorio en un script y debe de correr el código sin problema alguno.

Entonces pensando en que hay más usuario de Windows que de Linux, los detalles para correr el código que comentaré requiere probar que está bien instalado Python , configurar la variable PATH para correr Python desde la consola cmd o desde powershell y en caso de que se haga uso de Notepad++, se puede configurar para enviar el código a la consola y correrlos en el IDLE.

Creo que la mejor recomendación es empezar a usar Ipython y cualquier editor de texto, puede ser simplemente el notepad, pero se pueden revisar las recomendaciones en el libro online que mencioné anteriormente para ver como correr un scrip de python y como interactuar con el intérprete. Si presionan en la palabra “interprete”, podrán ver una versión online en la página oficial de python.

El párrafo anterior desalienta un poco cuando uno usa R project, por que solo basta instalar R, instalar las librerías y listo. Pero usar Python da oportunidad de conocer mejor como funciona aspecto del sistema, de la creación de una aplicación y de una que otra cosa que termina sirviendo posteriormente.

Lo que suele pasar con los usuarios de R es que pocas ocasiones desarrollan Script de R y los corren en la consola del sistema, el cmd en Windows. Esto cuando uno está iniciando a programar es raro, pero es fundamental para poder ponerse hacer cosas más interesantes.

Algunas aclaraciones, Notepad++ es un editor de texto más amigable y con más detalles y herramientas que el notepad normal, es de libre descarga y entre los lenguajes que soporta está Python. El IDLE que vienen en la descarga usual de Python es sencillo y lo único que se debe de revisar es como crear un archivo para ejecutar el código, que es cosa simple. Por supuesto que existen otros editores de texto y otros IDLE, depende del gusto de cada persona, pero la idea es la misma, de hecho directamente los IDLE no requieren otro editor como  Notepad++, en mi caso es por que me gusta más usar este último que escribir código directamente en el IDLE. Por último, lo recomendable es usar Ipython y una editor de texto eso basta para tener un entorno de trabajo con todos los recursos para trabajar con Python.

Un poco de Numpy

Esta librería permite la manipulación de arreglos o matrices de datos, en consecuencia también el manejo de vectores que son matrices de un solo renglón. Permite hacer operaciones aritméticas sobre todos los elementos de la matriz o elegir entre ellos bajo condiciones pedidas.

Haciendo un poco de memoria sobre las operaciones con matrices en álgebra lineal, en general uno estudia la dimensión de la matriz, la forma, el tipo de entradas que tiene, la multiplicación de matrices por un escalar, la suma y resta de matrices, el cálculo de la inversa de una matriz, el producto de matrices, el producto de una matriz y un vector, el producto interno de dos vectores o de las columnas de una matriz.

Este tipo de operaciones algebráicas se realizan con Numpy; algo extra es la manipulación de las entradas cuando se cuentan con datos NaN o eligiendo aquellas entradas que son mayores o menores algún valor, los que han usado Ovecta o Matlab.

En el código doy algunos ejemplos sencillos.

#Numpy
import numpy as np
#Creamos una matriz
a=np.array([0,1,2,3,4,5])
print 'Presenta la matriz'
print a
print 'Dimension de la matriz'
print a.ndim
#Vemos sus dimesión
print 'Forma de la matriz'
print a.shape
#Vemos su forma, el número de renglones y columnas
print 'Multiplica cada entrada por 2'
print a*2 
#Multiplicamos cada entrada por 2
print 'Eleva a la potencia 2 cada entrada'
print a**2
#Elevamos a la segunda potencia cada entrada
print 'Cambiando la forma del la matriz'
print a.reshape((3,2))
print 'Se imprime cada uno de sus elementos'
print a[0],a[1],a[2]
a[0]=5
print 'Se cambia la primera entrada a[0]=5'
print a
#Creamos una nueva matriz para de más dimensiones
b=np.array([[0,1,2],[3,4,5]])
print 'Se presenta b'
print b
print 'La forma de b'
print b.shape
print 'Se multiplica cada entrada por 3'
print b*3
print 'Se eleva cada entrada al cuadrado'
print b**2
#Se eliminan el vector y la matriz
del(a,b)


#Creacion de matrices especiales

a=np.zeros((3,4))
print 'Se presenta la matriz nula de 3X4'
print a
b=np.ones((2,2))

print 'Se presenta la matriz de unos'
print b
#Se creo la matriz con un valor igual para todas las entradas
c=np.full((3,3),3.5)
print 'Se presenta la matriz con valores iguales en todas las entradas'
print c

#Matriz identidad

d=np.eye(5)

print 'Se presenta la matriz identida de dimension 5'
print d

#Matriz con valores aleatorios

e=np.random.random((7,7))
print 'Se preseta la matri con valores aleatorios en cada entrada'
print e
#Eliminamos las matrices
del(a,b,c,d,e)

#Algunos detalles con los valores de las matrices y asignaciones

a=np.array([[1,2,3],[4,5,6],[7,8,9]])
print 'Se presenta la nueva matriz a'
print a
print 'Se presenta el valor de sus colnas'
print a[:,2]
#Se presentan las dos primeras filas
print 'Se presentan las dos primeras filas'
print a[:2,:]
#Creamos una nueva matriz con las primeras 4 entradas de a

b=a[:2,:2]
print 'Sub matriz de a'
print b
print 'modificamos el valor de b y modifica el de a'
b[0][0]=65
print b
print 'Modifica a'
print a
#esto tiene que ver con la asignación de memoria y de valores por python
del(a,b)
#Operaciones matematicas
a=np.array([[1,2,3],[4,5,6],[7,8,9]], dtype=np.float64)
b=np.array([[1,0,1],[2,6,1],[1,1,1]], dtype=np.float64)
#Suma de matrices
print a+b
print np.add(a,b)
#Resta de matrices
print a-b
print np.subtract(a,b)

#Multiplicacion
print a*b
print np.multiply(a,b) 

#division
print b/a 
print np.divide(b,a)

#Raiz cuadrada

print np.sqrt(a) 

#Producto interno de vectores y de vectores con matrices

c=np.array([1,0,1])

print 'Produto interno por (1,0,1)'
print a.dot(c)
print 'Producto punto de matrices'
print a.dot(b)

print 'Valores de b'
print b
print 'elecci󮠤e valores mayores a 1'
print b[b>1]
print b>1
print 'Generamos otra matriz con un elemento NAN'
c=np.array([1,2,np.NAN,3,4])
print 'Presentamos su valor'
print c
print 'Identificamos los valores que son NAN'
print np.isnan(c)
print 'Elegimos los valores que no son NAN'
print c[~np.isnan(c)]

Puede haber evitado poner tanto comentario en pantalla o estar enviando “print” en cada orden y comentario, pero los dejo así sobre todo para gente que recién inicia a manejar Python y le pueda causar confusión solo ver números y no saber que cosa es lo que está haciendo.

Si se pone atención el objeto sobre el cual se trabaja siempre es np y de él se toman lo necesitado para crear el tipo de matrices que se desea.

Algunas cosas que no comenté son las operaciones como suma de valores en la columna o de valores en la fila, la transpuesta y el asignar a una matriz para que tengas valores enteros o flotantes. Esto es sencillo y se puede consultar en la documentación de NumPy.

Algo de SciPy y Matplotlib

Como antes mencioné SciPy es una caja de herramientas y Matplotlib es una librería para graficar. Dos ejemplo son los siguientes:

#Dos ejemplos de Scipy
#Cargamos los módulos necesarios
import numpy as np
from scipy import signal, misc
import matplotlib.pyplot as plt

#Se revisará una imagen como dato

image = misc.lena().astype(np.float32)
derfilt = np.array([1.0, -2, 1.0], dtype=np.float32)
ck = signal.cspline2d(image, 8.0)
deriv = (signal.sepfir2d(ck, derfilt, [1]) +
 signal.sepfir2d(ck, [1], derfilt))

#Se calcula el Lapaciano

laplacian = np.array([[0,1,0], [1,-4,1], [0,1,0]], dtype=np.float32)
deriv2 = signal.convolve2d(ck,laplacian,mode='same',boundary='symm')

#Se presenta la imagen
plt.figure()
plt.imshow(image)
plt.gray()
plt.title('Original image')
plt.show()

#Se presenta la imagen modificada por el filtro y la señal gaussiana

image = misc.lena()
w = signal.gaussian(50, 5.0)
image_new = signal.sepfir2d(image, w, w)
plt.figure()
plt.imshow(image_new)
plt.gray()
plt.title('Filtered image')
plt.show()

Las imágenes  que obtenemos es:

figura_1

 

Este es un ejemplo clásico de SciPy, la siguiente foto, generada por las últimas líneas del programa anterior no regresan la siguiente modificación a la imagen. Qué lo que se hace es extraer como señal gaussiana o filtrar la imagen original, esto lo pueden consultar en la página de SciPy o en textos de procesamiento de imágenes.

figure_2

 

Otro ejemplo estándar para usar SciPy es en el análisis de señales.

#Análisis de señales
from numpy import arange, sin, pi, random, array
x = arange(0, 6e-2, 6e-2 / 30)
A, k, theta = 10, 1.0 / 3e-2, pi / 6
y_true = A * sin(2 * pi * k * x + theta)
y_meas = y_true + 2*random.randn(len(x))

def residuals(p, y, x):
 A, k, theta = p
 err = y - A * sin(2 * pi * k * x + theta)
 return err

def peval(x, p):
 return p[0] * sin(2 * pi * p[1] * x + p[2])

p0 = [8, 1 / 2.3e-2, pi / 3]
print(array(p0))


from scipy.optimize import leastsq
plsq = leastsq(residuals, p0, args=(y_meas, x))
print(plsq[0])


print(array([A, k, theta]))


import matplotlib.pyplot as plt
plt.plot(x, peval(x, plsq[0]),x,y_meas,'o',x,y_true)
plt.title('Datos con Ruido')
plt.legend(['Estimacion', 'Ruido', 'True'])
plt.show()

figure_3

Observamos que todo el proceso anterior es el que se realiza para analizar una señal, se considera el ruido, se estima una curva y se analiza con respecto a los datos originales.

Los dos códigos anteriores son ejemplos de como se usa SciPy en dos contextos distintos, uno con números y otro con imágenes. Se puede consultar muchos ejemplos en la página oficial de SciPy y Matplotlib.

El último ejemplo es tomado del texto de “Building Machine Learning Systems with Python” y los datos se pueden descargar desde GitHub. La idea de lo siguiente es graficar el cruce entre datos de tráfico web y semanas, pero además agregar curvas ajustadas a los datos.

#Se simplifica el código presentado en el texto
import os
from utils import DATA_DIR
import scipy as sp
import matplotlib.pyplot as plt

 
sp.random.seed(3) 
data = sp.genfromtxt(os.path.join(DATA_DIR, "web_traffic.tsv"), delimiter="\t")
print(data[:10])
print(data.shape)

#Se separan los datos en x e y
x = data[:,0]
y = data[:,1]
print("Entradas no validas:", sp.sum(sp.isnan(y)))

#Se limpian los datos
x = x[~sp.isnan(y)]
y = y[~sp.isnan(y)]

#Modelo 1
fp1= sp.polyfit(x, y, 1)
f1 = sp.poly1d(fp1)
fx = sp.linspace(0,x[-1], 1000)
#Modelo 2
f2p = sp.polyfit(x, y, 2)
f2 = sp.poly1d(f2p)

#Gráfica de los modelos y los datos 
plt.scatter(x,y)
plt.title("Trafico Web en un Mes")
plt.xlabel("Tiempo")
plt.ylabel("Hits/hora")
plt.xticks([w*7*24 for w in range(10)],['Semana %i'%w for w in range(10)])
#Se agregan los ajustes
plt.plot(fx, f1(fx), linewidth=4)
plt.plot(fx, f2(fx), linewidth=4)
#Se agregan las leyendas de las curvas
plt.legend(["d=1","d=2"], loc="upper left")
plt.autoscale(tight=True)
plt.grid()
#Se muestra la gráfica en la pantalla
plt.show()

La gráfica que se obtienen es la siguiente:

figure_4

Si uno revisa el último código, se observa que se importan las librerías usuales, SciPy y Matplotlib, pero además la librería os (sistema operativo) y un módulo de nombre utils. Existe un módulo en Python con el nombre de utils, pero lo que realmente se está haciendo es usar un script escrito por Willi Richert y Luis Pedro Coelho, que son los autores de dicho libro, para extraer los datos de un archivo con el nombre de “web_traffic.tsv” desde algún directorio. Si solo se descargan los datos y se quiere correr el código en algún directorio  arbitrario donde no se encuentre ni los datos ni el archivo utils, Python no enviará un error.

Entonces para este último ejemplo es recomendable descargar el código en zip de GitHub del libro y revisar el código de los autores del libro.

Con estos ejemplos espero se de una idea de como se hace uso de Numpy, SciPy y Matplotlib. Sobre las otras librerías, en cada entrada comento lo necesario, pero cada uno tienen sus detalles al momento de usarlas. En algunos casos, como IPython, uno puede hacer uso de Python sin recurrir a su uso, pero no esta de más conocer el por qué es altamente usada y ya con la práctica terminaran convencidos de su utilidad.

Referencias:

1.-http://www.creativebloq.com/design-tools/data-visualization-712402

Libros:

1.-http://www.amazon.es/Building-Machine-Learning-Systems-Python/dp/1782161406

2.-http://www.amazon.es/Learning-Python-Mark-Lutz/dp/1449355730/ref=sr_1_1?s=foreign-books&ie=UTF8&qid=1431492984&sr=1-1&keywords=Python

3.-http://www.amazon.es/Python-Data-Analysis-Wrangling-IPython/dp/1449319793/ref=sr_1_6?s=foreign-books&ie=UTF8&qid=1431493009&sr=1-6&keywords=Python

4.-http://www.amazon.es/High-Performance-Python-Performant-Programming/dp/1449361595/ref=sr_1_11?s=foreign-books&ie=UTF8&qid=1431493009&sr=1-11&keywords=Python

5.-http://www.amazon.es/Natural-Language-Processing-Python-Steven/dp/0596516495/ref=sr_1_94?s=foreign-books&ie=UTF8&qid=1431493443&sr=1-94&keywords=Python

6.-http://www.amazon.es/Building-Machine-Learning-Systems-Python-ebook/dp/B00VAG2WU4/ref=sr_1_126?s=foreign-books&ie=UTF8&qid=1431493491&sr=1-126&keywords=Python