Showing posts with label R. Show all posts
Showing posts with label R. Show all posts

Wednesday, May 18, 2022

¿Qué es Nylas, por qué me uní y porque debería importarles?



Me uní a Nylas más o menos hace 4 meses como su primer Senior Developer Advocate. Puede parecer un tiempo muy corto, pero en el mundo de los startups, el tiempo se mueve de forma diferente.

Aviso: Este post está escrito en Español, pensado en desarrolladores de habla hispana, pero no significa que Nylas ofrezca contenido, soporte o servicios en Español. Todo servicio es ofrecido únicamente en Inglés.

¿Qué es Nylas?


En palabras sencillas, Nylas es un grupo de APIs que nos permiten conectarnos de manera sencilla con cualquier proveedor de correo, calendario y contactos sin tener que pasar por ningún tipo de proceso largo y tedioso.

En otras palabras, hacemos el trabajo pesado para que ustedes puedan enfocarse en tu negocio.


Si hablamos de Email, ofrecemos “Un API de Correo para cualquier proveedor”. Esto significa que nuestro API de Correo es universal y puedes conectarte con varios proveedores sin tener la necesidad de escribir código específico para cada uno de ellos. Además, proveemos capacidades de tiempo real, sincronización bi-direccional, y full CRUD (Crear, Leer, Actualizar, Borrar). Si quieres saber más, solo tienes que ir a nuestra página Universal Email API.


Cuando se trata de Calendarios, ofrecemos las mismas capacidades que en nuestro API de Correo API, pero también sincronización de conferencias, metadata de eventos, y webhooks programables. Si quieres saber más, solo tienes que ir a nuestra página Universal Calendar API.


Si hablamos de Contactos, podemos crear, actualizar o eliminar contactos en cualquier proveedor compatible. Si quieres saber más, solo tienes que ir a nuestra página Universal Contacts API.


Con APIs para Correos, Calendarios, y Contactos, solo estamos comenzando. Miren que más ofrecemos por encima de esos APIs para proveer a los desarrolladores aún más poder.

Con Neural API, explorar el mundo de AI y ML es muy sencillo, con modelos listos para utilizar que pueden ser utilizados para limpiar conversaciones, extraer firmas, realizar OCR, y ejecutar análisis de sentimientos. Si quieres saber más, solo tienes que ir a nuestra página Neural API.With Neural API, exploring the world of AI and ML is easy, with ready-made models that can be used to clean conversations, extract signatures, perform OCR, and run sentiment analysis. If you want to learn more, just go to our Neural API page.


Nylas Streams es nuestra solución ETL que requiere muy poco o nada de código para transformar y consumir datos de comunicaciones para E-Commerce, Ventas, Fintech y Customer Success. Si quieres saber más, solo tienes que ir a nuestra página Nylas Streams.


Scheduler, un organizador completo con UI configurable. Si quieres saber más, solo tienes que ir a nuestra página Scheduler.


Components, widgets UI/UX completamente flexibles y listos para utilizar inmediatamente. Si quieres saber más, solo tienes que ir a nuestra página Components.


¿Por qué me uní?


Lo primero que llamó mi atención fue el hecho de que Nylas provee APIs que hacen que el manejo de comunicaciones sea mucho más sencillo. Manejar Correo, Calendarios y Contactos brinda mucho espacio para poder crear aplicaciones impresionantes.

Lo segundo que me atrajo de Nylas fue la cultura de la compañía. Todos se ven comprometidos los unos a los otros, puesto que vi mucho apoyo mutuo cuando la cuenta de Nylas posteaba algo en las redes sociales, y también mis entrevistas fueron más una conversación entre amigos que una entrevista de trabajo.

Lo tercero y probablemente más importante para mí, fue poder regresar a Developer Advocacy, que es algo que realmente me apasiona. Poder compartir con la comunidad de desarrolladores es algo que me hace sentir bien y que me hace una mejor persona y un mejor desarrollador.

Obviamente, estas 3 cosas no van a ser suficientes para convencerlos, así que he creado un par de pequeños ejemplos.

Para esto voy a utilizar uno de mis lenguajes de programación favoritos– R. Y aunque no soy un profesional de R ni tampoco un experto, es algo que me encanta, así que tenganme paciencia, deben hacer una manera mucho mejor de hacer esto.

Lo que vamos a hacer, es simplemente leer los primeros tres mensajes de nuestro inbox e imprimir los títulos.


El resultado va a ser:

A Nylas email 
Invitation: RRSP Webinar @ Tue Feb 8, 2022 1pm - 2pm (EST) (alvaro.t@nylas.com) 
Start here: Welcome to Clockwise


Obviamente, aunque R es un lenguaje asombroso utilizado por Estatistas y Data Scientists alrededor del mundo, no es un lenguaje utilizado por las masas.

Es por esto que Nylas provee SDKs para Python, Ruby, Node, y Java.

Veamos como podemos leer nuestro inbox utilizando el SDK de Python. Si quieres saber como instalar el SDK, puedes leer nuestra documentación Python Documentation.


El resultado va a ser:

A Nylas email 
Invitation: RRSP Webinar @ Tue Feb 8, 2022 1pm - 2pm (EST) (alvaro.t@nylas.com) 
Start here: Welcome to Clockwise

Como podemos ver, utilizar el SDK es mucho más sencillo, porque no tenemos que navegar la respuesta JSON ni tampoco averiguar que número de elemento tenemos que imprimir. Además, si algo cambia internamente podemos estar tranquilos y saber que el SDK va a ser actualizado para reflejar cualquier cambio mientras que llamar directamente al API va a requerir trabajo manual extra. Y lo mismo sucede con el Calendario, Contactos y el resto de nuestras propuestas.

¿Por qué debería importarles?


Bueno, para empezar, soy su amigable Developer Advocate así que ya saben que voy a mantenerlos informados con información constante e interesante acerca de las APIs de Nylas. Además, crearse una cuenta en Nylas es sencillo, no se necesita tarjeta de crédito y obtenemos 14 días para probar el producto. Listos para comenzar? Solo deben ir a https://dashboard.nylas.com/register y seguir las instrucciones.

Además, estoy trabajando en una serie de posts para ayudarlos a dar sus primeros pasos, hacer sus primeras llamadas a las APIs y en general, ayudarlos a obtener lo mejor de su experiencia con Nylas.

Pueden comenzar leyendo mi post How to Send Emails with the Nylas Python SDK

¿Piensas que Nylas no es para ti? Bueno, entonces recomiéndanos con tus amigos. Puedes conocer a alguien que se puede beneficiar de tener una manera rápida, sencilla y conveniente de acceder a APIs universales de comunicación.

Thursday, September 24, 2015

R - Mi largo viaje

La primera vez que escuché algo sobre R, fué hace más o menos 4 años atrás...un par de semanas luego de unirme a SAP. En ese momento leí en uno de nuestros documentos internos que SAP HANA iba a poder integrarse con el lenguaje de programacíón R.

Al inicio, estaba totalmente ignoránte acerca de R...nunca antes lo había escuchado...así que por supuesto comenzé a buscar más información, descargué R y RStudio y empecé a aprender como utilizarlo...

Luego de un tiempo...publiqué mi primer blog hablándo sobre R...esto fué el 28 de Noviembre del 2011...el blog fué Dealing with R and HANA...

Luego de eso, seguí aprendiendo y utilizándolo cada vez que podía...y terminé escribiéndo mi más exitoso blog en el SAP Community Network...esto fué el 21 de Mayo del 2012.


Que a la fecha tiene 21,879 vistas y 62 comentarios, 16 likes y 32 bookmarks.

R es inmenso...realmente lo es...existen cientos de paquetes que resuelven cientos de problemas...así es que comencé a leet libros relacionados con R de mis buenos amigos de Packt Publishing...




A medida que mis habilidades en R iban mejorándo...sabía que algo me estaba faltándo...realmente no sabía mucho sobre Estadística y mis habilidades de Machine Learning eran bastante pobres...y ahí es donde leí otro libro asombroso...y creo que hasta ahora es mi libro favorito sobre R

Machine Learning with R (Pueden leer mi review aquí).



Otro tópico interesánte es Social Media...y como obtener valor de sus datos...

Social Media Mining with R (Pueden leer mi review aquí).



Si se preguntan como el Social Media puede ser utilizado con R, entonces revisen mi blog Getting Flexible with SAP HANA donde utilizo SAP HANA, R, Twitter y Schema Flexibility para analizar hashtags que pueden ser explorados a más profundidad utilizándo herramientas como SAP Lumira.

Si estás en el mundo de la Bioinformática...en el cual no estoy yo -:( Podrían apreciar este libro...

Bioinformatics with R Cookbook (Pueden leet mi review aquí).


Y hay también otros libros que no he podido leer aún, pero que podrían ayudarlos a ingresar al mundo de R...


Así que...por qué son importante estos libros? Bueno...obviamente, todos son sobre R y R es asombroso y su importancia está subiendo cada día más...

Miren este video para darse cuenta de porque Data Science es un tópico crítico para aprender actualmente...

O pueden simplemente descargar un bonito PDF para leerlo offline http://bit.ly/1MryNha

También...tan solo con leer este post...tienen la oportunidad de comprar cualquiera de estos libros con un 50% de descuento utilizándo este código al momento del checkout...

SIXRB50


Una gran oportunidad que NO se puede dejar pasar...


La validez de este código expira el 31 de Octubre. Copias limitadas.

Saludos,

Blag.
Development Culture.

Monday, June 29, 2015

Explorando SparkR

Un compañero de trabajo, me pidió que investigara sobre Spark y R. Así que lo más obvio era investigar sobre SparkR -;)

Instalé Scala, Hadoop, Spark y SparkR...no estoy seguro si Hadoop es necesario en este caso...pero quería tener la imagen completa -:)

En fín...me encontré con un código que lee líneas de un archivo y cuenta cuantas líneas tienen una "a" y cuantas lineas tienen una "b"...

Para este código utilicé la letra de Girls Not Grey por AFI...

SparkR.R
library(SparkR)

start.time <- Sys.time()
sc <- sparkR.init(master="local")
logFile <- "/home/blag/R_Codes/Girls_Not_Grey"
logData <- SparkR:::textFile(sc, logFile)
numAs <- count(SparkR:::filterRDD(logData, function(s) { grepl("a", s) }))
numBs <- count(SparkR:::filterRDD(logData, function(s) { grepl("b", s) }))
paste("Lines with a: ", numAs, ", Lines with b: ", numBs, sep="")
end.time <- Sys.time()
time.taken <- end.time - start.time
time.taken



0.3167355 segundos...bastante rápido...me pregunto como le iría al R regular?

PlainR.R
library("stringr")

start.time <- Sys.time()
logFile <- "/home/blag/R_Codes/Girls_Not_Grey"
logfile<-read.table(logFile,header = F, fill = T)
logfile<-apply(logfile[,], 1, function(x) paste(x, collapse=" "))
df<-data.frame(lines=logfile)
a<-sum(apply(df,1,function(x) grepl("a",x)))
b<-sum(apply(df,1,function(x) grepl("b",x)))
paste("Lines with a: ", a, ", Lines with b: ", b, sep="")
end.time <- Sys.time()
time.taken <- end.time - start.time
time.taken


Que bueno...0.01522398 segundos...espera...qué? No se supone que Spark sea mucho más veloz? Bueno...recuerdo haber leído en algun lado que Spark brilla con archivos grandes...

Bueno...preparé un archivo con 5 columnas y 1 millón de registros...veamos como vá...

SparkR.R
library(SparkR)

start.time <- Sys.time()
sc <- sparkR.init(master="local")
logFile <- "/home/blag/R_Codes/Doc_Header.csv"
logData <- SparkR:::textFile(sc, logFile)
numAs <- count(SparkR:::filterRDD(logData, function(s) { grepl("a", s) }))
numBs <- count(SparkR:::filterRDD(logData, function(s) { grepl("b", s) }))
paste("Lines with a: ", numAs, ", Lines with b: ", numBs, sep="")
end.time <- Sys.time()
time.taken <- end.time - start.time
time.taken



26.45734 segundos para 1 millón de registros? Buen trabajo -:) Veamos si el R regular gana nuevamente...

PlainR.R
library("stringr")

start.time <- Sys.time()
logFile <- "/home/blag/R_Codes/Doc_Header.csv"
logfile<-read.csv(logFile,header = F)
logfile<-apply(logfile[,], 1, function(x) paste(x, collapse=" "))
df<-data.frame(lines=logfile)
a<-sum(apply(df,1,function(x) grepl("a",x)))
b<-sum(apply(df,1,function(x) grepl("b",x)))
paste("Lines with a: ", a, ", Lines with b: ", b, sep="")
end.time <- Sys.time()
time.taken <- end.time - start.time
time.taken


48.31641 segundos? Parece que Spark fué prácticamente el doble de rápido esta vez...y este es un ejemplo de lo más sencillo...estoy seguro de que cuando la complejidad aumenta...la brecha es aún más grande...

Y seguro...Yo sé que mucha gente puede tomar mi código en  R y hacerlo aún más veloz que Spark...pero...este es mi blog...no el de ellos -;)

Regresaré apenas sepa más sobre SparkR -:D

Saludos,

Blag.
Development Culture.

Friday, August 29, 2014

LED es mi nuevo Hello World - Tiempo de R

Sip...como he dicho antes muchas veces, la aplicación de números LED se ha convertido en mi nuevo Hello World...cada vez que aprendo un nuevo lenguaje de programación trato de construir esto, porque incluye varios comandos que son distintos en cada lenguaje y te hace aprender más mientras intentas construirlo en un lenguaje que no haz usado antes...

Ayer escribí un blog sobre como hacer esto con Haskell...y...aún estoy aprendiendo Haskell...así que pensé..."Es excelente que esté haciendo esto para nuevos lenguajes de programación...pero que pasa con los antiguos?"

De pronto me di cuenta de que nunca había escrito la aplicación utilizandoR...y eso es realmente triste...Me encanta R -:)

En fín...ahí les va -;)

LED.R
line<-c(1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3)
index<-c(0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,8,8,8,9,9,9)
map<-c("  _ ","| | ","|_| ","  ","| ","| ","  _ "," _| ","|_  ",
       " _","_| ","_| ","    ","|_| ","  | ","  _ ","|_  "," _| ",
       "  _ ","|_  ","|_| "," _  "," |  "," |  ","  _ ","|_| ","|_| ",
       "  _ ","|_| "," _| ")

Lines<-cbind(line,index,map)
DF_Lines<-data.frame(Lines,stringsAsFactors=F)

line1<-""
line2<-""
line3<-""

p_number<-readline("Enter a number?: ")
l_number<-strsplit(p_number,"")
for(i in 1:nchar(p_number)){
  num_map<-DF_Lines[DF_Lines$index == as.numeric(l_number[[1]][i]),]
  line1<-paste(line1,num_map$map[1])
  line2<-paste(line2,num_map$map[2])
  line3<-paste(line3,num_map$map[3])
}
lines = paste(line1,"\n",line2,"\n",line3,"\n")
cat(lines)

Miren la figura -;)


Saludos,

Blag.
Development Culture.

Friday, August 08, 2014

Bioinformatics with R Cookbook - Review del libro

Acabo de terminar de leer Bioinformatics with R Cookbook...así que aquí está mi review -:)



Estaba muy emocionado por leer este libro, porque hace ha pasado mucho desde que leí un libro sobre R...pero...debo admitirlo...este no es mi tipo de libro...puesto que descubrí que tengo una experiencia de menos uno en Bioinformatics...

Este libro no es corto pero tampoco es largo...340 páginas...y está lleno de recetas...

Empieza con una breve introducción a R, que debe ser apreciada por los principiantes...pero para desarrolladores más experimentados, eso se puede saltear...

Hay capítulos dedicados a Sequence Analysis, Protein Structure Analysis y hasta Machine Learning en Bioinformatics...

Por supuesto hay muchos nuevos paquetes que son usados para las recetas así como muchos grágicos interesántes...




Si tienes algún conocimiento sobre Bioinformatics...tu deberías de hecho conseguirte este libro...si no...bueno...puedes comprarlo de todos modos...aún si no entiendes nada de nada...igual es un libro sobre R y está lleno de códigos interesántes...así que a las finales terminarás aprendiendo muchas cosas nuevas -;)

Las recetas están bien explicadas y los resultados simpre están disponibles...lo cual es bueno porque así sabes exactamente que es lo que debes esperar...

Saludos,

Blag.
Development Culture.



Thursday, May 15, 2014

Social Media Mining with R - Review del libro

Estaba muy emocionado cuando mis amigos de Packt Publishing me enviaron este libro...puesto que no había leído ningún libro de R en bastante tiempo...pero no me entiendan mal...el libro no es malo...es solo que yo me esperaba un poco más...dejenme explicarlo un poco más...


El libro no es muy grande, que es algo que agradezco...son solo 122 páginas...viene con una pequeña introducción a R que es bueno para principiantes y luego va directamente a Social Media Mining utilizando Twitter.


El problema que tengo con este libro...y eso quizás no es totalmente malo...tiene más explicación sobre Social Media Mining que código fuente...así que claro, hace un excelente trabajo explicando como funciona el Social Media Mining pero para un desarrollador extremo como yo...el código fuente es lo más importante...


Para ser honesto...compraría este libro si no tuviera ninguna experiencia de Social Media Mining....pero he trabajado y hecho muchas aplicación utilizándo R y Twitter en el pasado...así que...este libro no es realmente para mi...

Saludos,

Blag.
Development Culture.

Monday, January 06, 2014

Machine Learning with R - Review del Libro

Debo admitirlo...soy un adicto a R...desde el primer momento que comencé a aprender R..se ha convertido en una adicción para mí...trato de resolver cualquier problema con R...la cual es obviamente no la mejor manera de proceder...pero mi regla de oro es..."Inténtalo primero con R...de otro mode...solo utiliza algo más y después regresa a R" -;)

Esta vez estaba muy emocionado de leer un nuevo libro de R (bueno...quizás no es nuevo...pero es nuevo para mí) llamado Machine Learning with R...


Para mi est libro debería llamarse "El gran libro para nerds en R"...con 396 páginas...es libro es simplemente hermoso, impresionante y uno de los mejores libro de R que leído jamás...

Por supuesto...tengan en cuenta de que este no es un libro para principiantes...necesitas tener experiencia previa en R para poder compreder todo correctamente...así que si no eres un entusiasta de R...ayudate a ti mismo y lee el también asombroso The R Inferno...

Este libro por supuesto, contiene una pequeña introducción a los principales y más usados comandos de R como Vectores, Factores, Listas, Data Frames manipulación de datos.

Cuando el libro es realmente interesante es cuando la introducción a Machine Learning es presentada...


Es resumen...un algorimo de Machine Learning tomará un input...aprenderá algo y generará un resultado que nos ayudará a tomar una desición...simplemente magia pura -:)

Algunos de los algoritmos cubiertos en este libro...y cubiertos en una manera realmente simple y digerible con algunos de los mejor ejemplos que se podrían ocurrir...son estos...


  • Nearest Neighbor

  • naive Bayes 

  • Decision Trees 

  • Classification Rule Learners 

  • Linear Regression 

  • Regression Trees 

  • Model Trees 

  • Neural Networks 

  • Support Vector Machines 

  • Association Rules 

  • k-means Clustering

  • Un poco pesado, no? Bueno...no realmente...R y su cornucopia de paquetes hacen que tu vida sea más fácil....luego de leer este libro...serás capaz de aplicar cada uno y todos los algoritmos en tus proyectos de la vida real...pero por supuesto...tu experiencia, prueba y error y perseverancia serán altamente apreciadas...

    Vamos algunos ejemplos...

    Cross table para un Nearest Neighbor

    Decision Tree

    Neural Network Diagram

    Association Rules

    Random Forests

    Impresionante, no? Por supuesto...pero la diversión no termina aquí...el libro nos ayuda aún más...con temas como...
    • Performance del Modelo de Evaluación
    • Mejorando el Performance del Modelo
    • Temas avanzados en Machine Learning
    Si ya haz jugado antes con R y siempre te preguntáste que diablos significa Machine Learning y porque deberías aprenderlo...este libro es totalmente para tí...lo recomiendo 100%...

    Saludos,

    Blag.
    Developer Empowerment and Culture.

    Monday, December 02, 2013

    Batalla en Twitter

    Me encanta divertirme con Twitter y R...hay muchas cosas interesantes que se pueden hacer...así que pensé en tener una pequeña aplicación para tener una batalla en Twitter...algo que toma el número de seguidores y listas de dos usuarios...aplicar algunos algorimos mediocres y determinar la importancia en Twitter entre esos dos usuarios...utilizándo nuestro archivo .RData que contiene la información del OAuth en Twitter...

    Batalla en Twitter
    require("Rook")
    library("ROAuth")
    library("twitteR")
    
    setwd("C:/Blag/R_Scripts/Important_Scripts")
    load("credentials.RData")
    
    Get_Percentages<-function(p_one,p_two,flag){
          if(p_one > p_two){
            if(flag == 0){
              OneFollowPercent<-100
              TwoFollowPercent<-round((p_two * 100) / p_one)
            }else{
              TwoFollowPercent<-100 - (round((p_two * 100) / p_one))
              if(TwoFollowPercent <= 49){
                OneFollowPercent<-50 + TwoFollowPercent
                TwoFollowPercent<-100 - OneFollowPercent
                flag<-0
              }else{
                OneFollowPercent<-50 + TwoFollowPercent
                TwoFollowPercent<-100 - TwoFollowPercent
                TwoFollowPercent<-100 - round((round(TwoFollowPercent * 100) / OneFollowPercent))
                OneFollowPercent<-TwoFollowPercent
                TwoFollowPercent<-100 - OneFollowPercent
                flag<-1
              }
            }
          }
          if(p_one < p_two){
            if(flag == 0){
              OneFollowPercent<-round((p_one * 100) / p_two)
              TwoFollowPercent<-100
            }else{
              OneFollowPercent<-100 - (round((p_one * 100) / p_two))
              if(OneFollowPercent <= 49){
                TwoFollowPercent<-50 + OneFollowPercent
                OneFollowPercent<-100 - TwoFollowPercent
                flag<-0
              }else{
                TwoFollowPercent<-50 + OneFollowPercent
                OneFollowPercent<-100 - OneFollowPercent
                OneFollowPercent<-100 - round((round(OneFollowPercent * 100) / TwoFollowPercent))
                TwoFollowPercent<-OneFollowPercent
                OneFollowPercent<-100 - TwoFollowPercent
                flag<-1
              }
            }
          }
          if(p_one == p_two){
            OneFollowPercent<- 50
            TwoFollowPercent<- 50
          }
          percents<-c(OneFollowPercent,TwoFollowPercent,flag)
          return(percents)
    }
    
    newapp<-function(env){
      req<-Rook::Request$new(env)
      res<-Rook::Response$new()
      res$write('<form method="POST">\n')
      res$write('Enter your Twitter username: <input type="text" name="YourUserName">')
      res$write('</BR>')
      res$write('Enter your his/her Twitter username: <input type="text" name="HisHerUserName">')
      res$write('</BR>')
      res$write('<input type="submit" name="Start the Battle!">')
      res$write('</form>')
        
      if (!is.null(req$POST())) {
        YourUserName = paste("@",req$POST()[["YourUserName"]],sep="")
        HisHerUserName = paste("@",req$POST()[["HisHerUserName"]],sep="")
        
        reg<-registerTwitterOAuth(credentials)
        
        GetYourUser<-getUser(YourUserName,cainfo="cacert.pem")
        GetHisHerUser<-getUser(HisHerUserName,cainfo="cacert.pem")
        
        GetYourFollowers<-GetYourUser$followersCount
        GetYourLists<-GetYourUser$listedCount
        GetHisHerFollowers<-GetHisHerUser$followersCount
        GetHisHerLists<-GetHisHerUser$listedCount
    
        FollowPercents<-Get_Percentages(GetYourFollowers,GetHisHerFollowers,0)
        ListPercents<-Get_Percentages(GetYourLists,GetHisHerLists,0)
    
        YourPercents<-FollowPercents[1] + ListPercents[1]
        HisHerPercents<-FollowPercents[2] + ListPercents[2]
    
        FinalPercents<-Get_Percentages(YourPercents,HisHerPercents,1)
    
        YourPercents<-FinalPercents[1]
        HisHerPercents<-FinalPercents[2]
        if(FinalPercents[3] == 0){
          DiffPercent<-abs(YourPercents - 50)
        }else{
          DiffPercent<-FinalPercents[1]
        }
        
        if(YourPercents > HisHerPercents){
          message<-paste(req$POST()[["YourUserName"]],"is",DiffPercent,
                         " % more important on Twitter than",req$POST()[["HisHerUserName"]],sep=" ")
          res$write(paste('<H1>',message,'</H1>'))   
        }
        if(YourPercents < HisHerPercents){
          message<-paste(req$POST()[["YourUserName"]],"is",DiffPercent,
                         " % less important on Twitter than",req$POST()[["HisHerUserName"]],sep=" ")
          res$write(paste('<H1>',message,'</H1>'))
        }
        if(YourPercents == HisHerPercents){
          message<-paste(req$POST()[["YourUserName"]],
                         "is equally important on Twitter as",req$POST()[["HisHerUserName"]],sep=" ")
          res$write(paste('<H1>',message,'</H1>'))
        }
        
        pieValues<-c(YourPercents,HisHerPercents)
        pieNames<-c(paste(req$POST()[["YourUserName"]],YourPercents,"%"),
                          paste(req$POST()[["HisHerUserName"]],HisHerPercents,"%"))
        
        png("Twitter_Battle.png",width=1000,height=700)
        pie(pieValues,labels=pieNames,main="Twitter Battle")
        dev.off()
        res$write("<div align='center'>")
        res$write(paste("<img src='", server$full_url("pic"), "/", 
                        "Twitter_Battle.png'", "/>", sep = ""))
        
        res$write("</div>")
    }
      res$finish()
    }
    
    server = Rhttpd$new()
    server$add(app = newapp, name = "Twitter_Battle")
    server$add(app = File$new("C:/Blag/R_Scripts/Important_Scripts"), name = "pic")
    server$start()
    server$browse("Twitter_Battle")
    

    Cuando lo ejecutamos...vamos a tener algunos interesantes resultados...




    Que se diviertan con esto -;)

    Saludos,

    Blag.

    Unseguidores en Twitter con R y Rook - Revisitado

    Hace algún tiempo escribí un blog llamado Unseguidores en Twitter con R y Rook donde utilicé R y Twitter para obtener una lista de las personas que seguimos...pero que no nos siguen a nostros...

    Ahora...ese post es obsoleto puesto que Twitter cambió su API a API 1.1 lo cuál significa que la autenticación OAuth debe ser usada...

    Así que...por supuesto...vamos a utilizar eso para nuestra nueva versión del Unseguidores con Twitter -;)

    Obteniendo el Twitter Auth
    library("ROAuth")
    library("twitteR")
    
    setwd("C:/Blag/R_Scripts/Important_Scripts")
    
    options(RCurlOptions = list( capath = system.file("CurlSSL", "cacert.pem", package = "RCurl"), ssl.verifypeer = FALSE))
    
    reqURL<-"https://api.twitter.com/oauth/request_token"
    
    accessURL<-"http://api.twitter.com/oauth/access_token"
    
    authURL<-"http://api.twitter.com/oauth/authorize"
    
    consumerKey<-"Your own Consumer Key"
    
    consumerSecret<-"Your own Consumer Secret"
    
    download.file(url="http://curl.haxx.se/ca/cacert.pem", destfile="cacert.pem")
    
    credentials<-OAuthFactory$new(consumerKey=consumerKey,
                                  consumerSecret=consumerSecret,
                                  requestURL=reqURL,
                                  accessURL=accessURL,
                                  authURL=authURL)
    
    credentials$handshake(cainfo = system.file("CurlSSL", "cacert.pem", package = "RCurl"))
    
    save(credentials, file="credentials.RData")
    

    Lo que estamos hacindo aquí es simplemente obtener la autorizacipin de Twitter y guardando esa información como un archivo RData que podremos utilizar más adelante. Este script necesita ser utilizado una sola vez...y te pedirá que ingreses un PIN para validar la conexión...


    Luego de eso...estamos listos para comenzar -;)

    Unseguidores en Twitter
    require("Rook")
    library("ROAuth")
    library("twitteR")
    
    setwd("C:/Blag/R_Scripts/Important_Scripts")
    load("credentials.RData")
    registerTwitterOAuth(credentials)
    Get_Screen_Name<-function(p_userid){
      SomeUser<-getUser(p_userid,cainfo="cacert.pem")
      SomeUser<-SomeUser$screenName
      return(SomeUser)
    }
    
    newapp<-function(env){
      req<-Rook::Request$new(env)
      res<-Rook::Response$new()
      res$write('<form method="POST">\n')
      res$write('Enter your Twitter username: <input type="text" name="UserName">\n')
      res$write('<input type="submit" name="Get Bad People!">')
      res$write('</form>')
      
      People_Id<-""
      Bad_People<-c()
      Bad_Names<-c()
      j<-0  
      
      if (!is.null(req$POST())) {
        UserName = req$POST()[["UserName"]]
        
        User<-userFactory$new(screenName=UserName)
        followers<-User$getFollowerIDs(n=NULL,cainfo="cacert.pem")
        following<-User$getFriendIDs(n=NULL,cainfo="cacert.pem")
    
        for(i in 1:length(following)) {
          Match<-following[i] %in% followers
          if(Match == TRUE){
          }
          else{
            Bad_Person<-Get_Screen_Name(following[i])
            res$write(paste(' ',Bad_Person,sep=' '))
            res$write('</BR>')
          }
        }
    }
      res$finish()
    }
    
    server = Rhttpd$new()
    server$add(app = newapp, name = "Twitter_Rook")
    server$start()
    server$browse("Twitter_Rook")
    

    Gracias a esto...pude reducir el código de 85 líneas de la versión anterior a solo 51 lineas de código...gran logro si me lo preguntan -;)

    Así que...cuando ejecutamos el código...tendremos esto...


    Por supuesto...No espero que todos me sigan de vuelta puesto que en su mayoría son empresas...pero para las personas...siganme o serán unseguidos -:P

    Saludos,

    Blag.

    Friday, September 06, 2013

    Ejecutando R dentro de SAP HANA Studio

    *PELIGRO* Este es solo un blog tonto y no deberia ser tomado seriamente.*PELIGRO*

    Ok...seguro se preguntaran...porque esta Blag escribiendo un blog tonto? Bueno...Soy un Developer Evangelist...y es mi deber mantener a los desarrolladores entretenidos -:) ademas...tenia un poco de tiempo libre -8)

    Como ya todos deben saber...SAP HANA Studio corre sobre Eclipse...lo cual significa que si podemos ejecutar R en Eclipse...podemos obviamente ejecutar R en SAP HANA Studio...eso es exactamente lo que vamos a hacer -;)

    Tan facil como suena...sigan estas instrucciones...

    • Vamos a Help --> Install New Software
    • Ponemos el siguiente repositorio

    • Escogemos Walware - StatET



    • Una vez instalado, nuestro SAP HANA Studio se reiniciara y deberemos connfigurar R.
    • Nos vamos a Windows --> Preferences.
    • StatET --> Run/Debug --> R Environments --> Add (En la imagen, estoy usando Edit puesto que yo ya lo agregue).




    • Ya sea en la linea de comandos o en RStudio, instalamos lo siguiente...
    • install.packages(c("rj", "rj.gd"), repos="http://download.walware.de/rj-1.1")
    • Tambien instalamos RJava...install.packages("RJava")

    Ahora...debemos iniciar la consola de R...asi que...
    • Vamos a la pequeño boton con Flecha Verde y presionamos "R_Console".


    Una vez que esto esta listo, podemos crear nuestro script en R...
    • Vamos a File --> New Project --> R Project.
    • En el proyecto R creado, hacemos doble click y seleccionamos New --> R Script File.



    Copiamos este codigo en el script R...

    R_from_SAP_HANA.sql
    result<-read.table('clipboard',header=TRUE,sep=';')
    result<-subset(result, !duplicated(DISTANCE))
    flights<-data.frame(DISTANCE=as.numeric(result$DISTANCE))
    row.names(flights)<-result$FLIGHT
    d<-dist(as.matrix(flights))
    hc<-hclust(d)
    plot(hc)
    

    Ahora...vamos a la perspectiva "Modeler"...abrimos una consola SQL y escribimos lo siguiente...

    SAP_HANA_Select.sql
    SELECT DISTINCT CITYFROM || '/' || CITYTO "FLIGHT", DISTANCE
    FROM SFLIGHT.SPFLI
    WHERE DISTANCE > 0
      AND CARRID = 'SQ'
    

    Lo ejecutamos...y aqui viene la parte graciosas...nos vamos al tab Result tab y seleccionamos todos los registros...luego seleccionamos Copy Rows, para que la seleccion quede grabada en el Clipboard.


    Regresamos a la perspectiva StatET y hacemos click en el boton "Run file in R via command"...



    Cuando ejecutamos el codigo...no vamos a ver ninguna respuesta, a menos que haya un error...asi que simplemente vamos al tab R Graphics tab que esta abajo, en el lugar donde el tab Console se ubica...lo expandimos...y podran ver un grafico de Cluster Dendogram generado -;)


    Se los dije...este es un post muy tonto...pero por lo menos...nunca dejamos SAP HANA Studio -:P

    Nos vemos la proxima vez!

    Blag.
    Developer Experience.

    Thursday, August 22, 2013

    Forecasting con Redes Neurales (usando SAP HANA y R)

    Usualmente...cuando uso R...trato de usar también SAP HANA...y la forma más simple de hacerlo trabajar es de hecho, haciendo una conexión ODBC....rápido y sencillo...

    Primero, me fuí a mi SAP HANA Studio para obtener el query...el cual es basicamente...obtener todos los asientos (Primera Clase, Business, Clase Económica) de todos los vuelos que sucedieron entre los años 2010 y 2012.

    Query from HANA Studio
    SELECT FLDATE, SEATSOCC, SEATSOCC_B, SEATSOCC_F 
    FROM SFLIGHT.SFLIGHT WHERE YEAR(FLDATE) BETWEEN '2010' AND '2012'
    

    El resultado se verá así...


    Pero...queremos tener todos los asientos sumarizados en una sola variable y tambien organizados por Mes/Año. Y aunque podemos hacer eso con SQL...eso le quitaría toda la diversión a R...

    Getting and formatting data
    library("RODBC")
    
    format_date<-function(p_date){
      p_date<-as.Date(as.character(p_date),"%Y%m%d")
      p_date<-format(p_date,"%Y%m")
      return(p_date)
    }
    
    ch<-odbcConnect("HANA",uid="SYSTEM",pwd="********")
    result<-sqlQuery(ch,"SELECT FLDATE, SEATSOCC, SEATSOCC_B, SEATSOCC_F 
                     FROM SFLIGHT.SFLIGHT WHERE YEAR(FLDATE) BETWEEN '2010' AND '2012'")
    odbcCloseAll()
    dates<-result$FLDATE
    dates<-format_date(dates)
    result$FLDATE = dates
    result_agg<-aggregate(cbind(SEATSOCC,SEATSOCC_B,SEATSOCC_F)~.,data=result,FUN=sum)
    result_total<-data.frame(FLDATE=result_agg$FLDATE,SEATS=result_agg$SEATSOCC+
                             result_agg$SEATSOCC_B+result_agg$SEATSOCC_F,stringsAsFactors=FALSE)
    

    Primero, usando la librería RODBC nos conectamos a nuestro servidor SAP HANA. Luego, tomamos las fechas y utilizado una función customizada, los convertimos a Mes/Año. Hacemos una agregación para obtener la suma de todos los asientos y luego construímos un Data Frame para poder manejar los datos.

    Cuando imprimos el resultado final...vamos a darnos cuenta de algo que seguramente había escapados de nuestros ojos...


    Para el 2010, los meses empiezan en Abril, lo cual significa que de Enero a Marzo no hay información...y lo mismo pasa con el 2012 donde la información termina en Abril y de Junio a Diciembre no hay nada.

    Como queremos hacer un Forecasting con Redes Neuronales...esta data incompleta no nos va a servir para nada...así que debemos hacer algo para corregir esto...

    Algo que podemos hacer, por lo menos para el 2012, es el Moving Average...que es basicamente tomar los valores de Eneto a Abril, sumarlos, dividirlos por el números de meses y luego asignar este valor a Mayo (201205)...luego...tomar el valor desde Febrero a Mayo y hacer los mismo para Junio...y seguir así -:)

    Para el 2010 paracer ser un poco más complicado...pero es casi lo mismo...utilizo algo que me gusta llamar Backward Average...sin importarme cual es un nombre real -:P Basicamente, tomamos los valores de Diciembre a Abril, sumarlos, dividirlos por el número de meses y determinar el valor para Marzo...y seguir así...

    Veamos el código...

    Moving and Backward Average
    library("RODBC")
    
    format_date<-function(p_date){
      p_date<-as.Date(as.character(p_date),"%Y%m%d")
      p_date<-format(p_date,"%Y%m")
      return(p_date)
    }
    
    moving_average<-function(p_values,year_start,month_start,year_end,month_end){
      month<-as.numeric(month_start) - 1
      init_month<-"01"
      if(length(month)==1){
        init_date<-paste(year_start,"0",month,sep='')
      }
      base_date<-paste(year_start,init_month,sep='')
      counter<-as.numeric(month_end) - as.numeric(month_start)
      
      values<-p_values
      
      for(i in 0:counter){
        values<-subset(values, FLDATE <= init_date & FLDATE >= base_date) 
        new_value<-floor(mean(values$SEATS))
        new_values<-data.frame(FLDATE=paste(year_start,month_start,sep=''),SEATS=new_value)
        p_values<-rbind(p_values,new_values)
        month_start<-as.numeric(month_start) + 1
        if(nchar(month_start)==1){
          month_start<-paste("0",month_start,sep='')
        }
        values<-rbind(values,new_values)
        month<-month + 1
        init_month<-as.numeric(init_month) + 1
        if(nchar(month)==1){
          init_date<-paste(year_start,"0",month,sep='')
        }else{
          init_date<-paste(year_start,month,sep='')
        }
        if(nchar(init_month)==1){
          base_date<-paste(year_start,"0",init_month,sep='')  
        }else{
          base_date<-paste(year_start,init_month,sep='')  
        }
      }
      return(p_values)
    }
    
    backward_average<-function(p_values,year_start,month_start,year_end,month_end){
      month<-as.numeric(month_start) - 1
      init_month<-"12"
      if(length(month)==1){
        init_date<-paste(year_start,"0",month,sep='')
      }
      base_date<-paste(year_start,init_month,sep='')
      counter<-as.numeric(month_start) - as.numeric(month_end)
      
      values<-p_values
      
      for(i in 0:counter){
        values<-subset(values, FLDATE <= base_date & FLDATE >= init_date) 
        new_value<-floor(mean(values$SEATS))
        new_values<-data.frame(FLDATE=paste(year_start,month_start,sep=''),SEATS=new_value)
        p_values<-rbind(p_values,new_values)
        month_start<-as.numeric(month_start) - 1
        if(nchar(month_start)==1){
          month_start<-paste("0",month_start,sep='')
        }
        values<-rbind(values,new_values)
        month<-month + 1
        init_month<-as.numeric(init_month) - 1
        if(nchar(month)==1){
          init_date<-paste(year_start,"0",month,sep='')
        }else{
          init_date<-paste(year_start,month,sep='')
        }
        if(nchar(init_month)==1){
          base_date<-paste(year_start,"0",init_month,sep='')  
        }else{
          base_date<-paste(year_start,init_month,sep='')  
        }
      }
      return(p_values)
    }
    
    ch<-odbcConnect("HANA",uid="SYSTEM",pwd="********")
    result<-sqlQuery(ch,"SELECT FLDATE, SEATSOCC, SEATSOCC_B, SEATSOCC_F 
                     FROM SFLIGHT.SFLIGHT WHERE YEAR(FLDATE) BETWEEN '2010' AND '2012'")
    odbcCloseAll()
    dates<-result$FLDATE
    dates<-format_date(dates)
    result$FLDATE = dates
    result_agg<-aggregate(cbind(SEATSOCC,SEATSOCC_B,SEATSOCC_F)~.,data=result,FUN=sum)
    result_total<-data.frame(FLDATE=result_agg$FLDATE,SEATS=result_agg$SEATSOCC+
                             result_agg$SEATSOCC_B+result_agg$SEATSOCC_F,stringsAsFactors=FALSE)
    result_total<-moving_average(result_total,"2012","05","2012","12")
    result_total<-backward_average(result_total,"2010","03","2010","01")
    

    Cuando ejecutamos...nos daremos cuenta que de hecho...tenemos los 3 años con valores completos -;)


    Ahora...podemos utilizar finalmente el Forecasting -;)

    Neural_Network_Forecasting.R
    library("RODBC")
    library("forecast")
    
    format_date<-function(p_date){
      p_date<-as.Date(as.character(p_date),"%Y%m%d")
      p_date<-format(p_date,"%Y%m")
      return(p_date)
    }
    
    moving_average<-function(p_values,year_start,month_start,year_end,month_end){
      month<-as.numeric(month_start) - 1
      init_month<-"01"
      if(length(month)==1){
        init_date<-paste(year_start,"0",month,sep='')
      }
      base_date<-paste(year_start,init_month,sep='')
      counter<-as.numeric(month_end) - as.numeric(month_start)
      
      values<-p_values
      
      for(i in 0:counter){
        values<-subset(values, FLDATE <= init_date & FLDATE >= base_date) 
        new_value<-floor(mean(values$SEATS))
        new_values<-data.frame(FLDATE=paste(year_start,month_start,sep=''),SEATS=new_value)
        p_values<-rbind(p_values,new_values)
        month_start<-as.numeric(month_start) + 1
        if(nchar(month_start)==1){
          month_start<-paste("0",month_start,sep='')
        }
        values<-rbind(values,new_values)
        month<-month + 1
        init_month<-as.numeric(init_month) + 1
        if(nchar(month)==1){
          init_date<-paste(year_start,"0",month,sep='')
        }else{
          init_date<-paste(year_start,month,sep='')
        }
        if(nchar(init_month)==1){
          base_date<-paste(year_start,"0",init_month,sep='')  
        }else{
          base_date<-paste(year_start,init_month,sep='')  
        }
      }
      return(p_values)
    }
    
    backward_average<-function(p_values,year_start,month_start,year_end,month_end){
      month<-as.numeric(month_start) - 1
      init_month<-"12"
      if(length(month)==1){
        init_date<-paste(year_start,"0",month,sep='')
      }
      base_date<-paste(year_start,init_month,sep='')
      counter<-as.numeric(month_start) - as.numeric(month_end)
      
      values<-p_values
      
      for(i in 0:counter){
        values<-subset(values, FLDATE <= base_date & FLDATE >= init_date) 
        new_value<-floor(mean(values$SEATS))
        new_values<-data.frame(FLDATE=paste(year_start,month_start,sep=''),SEATS=new_value)
        p_values<-rbind(p_values,new_values)
        month_start<-as.numeric(month_start) - 1
        if(nchar(month_start)==1){
          month_start<-paste("0",month_start,sep='')
        }
        values<-rbind(values,new_values)
        month<-month + 1
        init_month<-as.numeric(init_month) - 1
        if(nchar(month)==1){
          init_date<-paste(year_start,"0",month,sep='')
        }else{
          init_date<-paste(year_start,month,sep='')
        }
        if(nchar(init_month)==1){
          base_date<-paste(year_start,"0",init_month,sep='')  
        }else{
          base_date<-paste(year_start,init_month,sep='')  
        }
      }
      return(p_values)
    }
    
    ch<-odbcConnect("HANA",uid="SYSTEM",pwd="********")
    result<-sqlQuery(ch,"SELECT FLDATE, SEATSOCC, SEATSOCC_B, SEATSOCC_F 
                     FROM SFLIGHT.SFLIGHT WHERE YEAR(FLDATE) BETWEEN '2010' AND '2012'")
    odbcCloseAll()
    dates<-result$FLDATE
    dates<-format_date(dates)
    result$FLDATE = dates
    result_agg<-aggregate(cbind(SEATSOCC,SEATSOCC_B,SEATSOCC_F)~.,data=result,FUN=sum)
    result_total<-data.frame(FLDATE=result_agg$FLDATE,SEATS=result_agg$SEATSOCC+
                             result_agg$SEATSOCC_B+result_agg$SEATSOCC_F,stringsAsFactors=FALSE)
    result_total<-moving_average(result_total,"2012","05","2012","12")
    result_total<-backward_average(result_total,"2010","03","2010","01")
    result_total <- result_total[order(result_total$FLDATE),] 
    result_ts<-ts(result_total$SEATS,frequency=12,start=c(2010,1))
    
    fit <- nnetar(result_ts)
    fcast <- forecast(fit)
    plot(fcast)
    

    Veamos el gráfico generado...


    Como pueden ver...la predicción del 2013 al 2015 es muy baja...pero es simplemente por el hecho de que el 2012 fué un año muy bajo...

    Saludos,

    Blag.