Informes con R en HTML. Comienzo con R2HTML (I)

En las III jornadas de R tuve el placer de asistir al taller de Gregorio Serrano sobre informes con R. Me abrió los ojos. Siempre he pensado que R no es una herramienta que sirva para hacer informes [modo consultor = ON] R no servía para realizar reporting  [modo consultor = OFF]. Pero R tiene un poderoso motor gráfico y dispone del paquete R2HTML para poder realizar tablas en HTML y si trabajamos con libros CSS de estilos podemos obtener resultados muy atractivos. Así que la otra tarde me puse manos a la obra y creo que puede salir una trilogía interesante. Bueno, depende del interés que despierte esta entrada del blog haré más entregas, pero de momento tengo en mente llegar a 3.

Seguimos con el sistema habitual. Simulo unos datos de ejemplo que podéis copiar  y pegar en vuestra consola de R:

clientes=20000
saldo_vista=abs(rnorm(clientes,0,1)*10000+5000)
saldo_ppi=(runif(clientes,0.1,0.6)*rpois(clientes,2))*60000
saldo_fondos=abs(rnorm(clientes,0,1)*100000+3000)*(runif(clientes)>=0.6)
edad=rpois(clientes,60)
datos_ini<-data.frame(cbind(saldo_vista,saldo_ppi,saldo_fondos,edad))
datos_ini$saldo_ppi=(edad<65)*datos_ini$saldo_ppi
#Creamos la variable objetivo a partir de un potencial
datos_ini$potencial= runif(clientes,0,1)
datos_ini$potencial= datos_ini$potencial +
log(edad)/2 +
runif(1,0,0.03)*(saldo_vista>20000)+
runif(1,0,0.09)*(saldo_fondos>30000)+
runif(1,0,0.07)*(saldo_ppi>10000)
datos_ini$pvi=(datos_ini$potencial>=quantile(datos_ini$potencial,
0.85))*1
#Eliminamos la columna que genera nuestra variable dependiente
datos_ini = subset(datos_ini, select = -c(potencial))

Datos simulados de una entidad bancaria donde tenemos edad, saldos en distintos productos de pasivo e identificamos a aquellos clientes que tienen contratada una pensión vitalicia. Nos solicitan realizar un informe con los datos de contratación por edad y por pasivo. Cuando realizamos informes es muy habitual tramificar variables continuas. Para crear los tramos de edad y de pasivo vamos a emplear la función recode de la librería memisc:

#Con memisc recodifico los factores
library(memisc)
datos_ini$rango_edad <- recode(datos_ini$edad,
"1 Menos de 45 años" <- range(min,45),
"2 Entre 46 y 55 años" <- 46:55,
"3 Entre 56 y 65 años" <- 56:65,
"4 Más de 65 años" <- range(66,max))

datos_ini$rango_vista <- recode(datos_ini$saldo_vista,
"1 Menos de 5.000 €" <- range(min,5000),
"2 Entre 5.000 y 15.000 €" <- range(5000,15000),
"3 Entre 15.000 y 25.000 €" <- range(15000,25000),
"4 Más de 25.000 €" <- range(25000,max))

Los intervalos creados son cerrados por la derecha. En el blog se ha tratado en otra ocasión la recodificación de los factores y no se trabajó con memisc. Bajo mi punto de vista recode+memisc es la mejor opción. Ya tenemos nuestras variables recodificadas y ahora tenemos que sumarizar y graficar el número de clientes frente a las tasas de contratación. A la hora de realizar informes los formatos son muy importantes. Por defecto en R estamos acostumbrados a trabajar con formatos americanos, comas para separar decimales y puntos para separar miles. Esto a mi no me gusta, prefiero el formato americano. Por ello lo primero que hacemos es crearnos unas funciones que nos den formatos europeos y formatos en porcentaje:

#Función para dar formatos a los datos
#Separador de miles europeo
sep.miles <- function(x){
format(x,big.mark=".")}
#Creación de formatos de decimales
fmt.porcen <- function(x){
paste(format(round(x,2),decimal.mark = ","),'%')}

Estas funciones nos servirán para dar formatos a los números de nuestras tablas. ¿Cómo vamos a hacer las tablas? Con ddply por supuesto. Ahora las librerías plyr y ggplot2 son las que nos ayudarán a crear el informe:

library(plyr)
library(ggplot2)

#Realizamos la tabla de sumarización
resum1 <- ddply(datos_ini,"rango_edad",summarise,
clientes=length(rango_edad),
contrata=sum(pvi))
resum1$tasa=fmt.porcen(resum1$contrata*100/resum1$clientes)
resum1$clientes=sep.miles(resum1$clientes)
resum1$contrata=sep.miles(resum1$contrata)

#Pintamos un diagrama de barras
png(file="C:\\temp\\informes\\resum1.png",width=600, height=450)
a <- ggplot(datos_ini, aes(rango_edad,fill=factor(pvi)))
a + geom_bar()
dev.off()

resum2 <- ddply(datos_ini,"rango_vista",summarise,
clientes=length(rango_edad),
contrata=sum(pvi))
resum2$tasa=fmt.porcen(resum2$contrata*100/resum2$clientes)
resum2$clientes=sep.miles(resum2$clientes)
resum2$contrata=sep.miles(resum2$contrata)

png(file="C:\\temp\\informes\\resum2.png",width=600, height=450)
a <- ggplot(datos_ini, aes(rango_vista,fill=factor(pvi)))
a + geom_bar()
dev.off()

Mucho código. Los objetos resumx son las tablas que hemos de representar, son sumarizaciones del total de clientes y de los clientes que contratan el producto. Calculamos una tasa y aplicamos los correspondientes formatos. Al formatear los datos los números pasan a ser texto, en ese sentido R no es como otras herramientas, no provoca muchos problemas. El último paso es realizar el informe. Todo quedará almacenado en nuestro disco, en este caso trabajamos con Windows y guardamos el informe en C:\Temp\informes\:

<em>library(R2HTML) 
 
salida  = HTMLInitFile( "C:\\temp\\informes",filename="salida", 
 
CSSFile="C:\\TEMP\\informes\\table_design.css") 
 
HTML("&lt;div align=center&gt;") 
 
HTML("&lt;p align=center&gt;Estudio por edad&lt;/p&gt;" ,file=salida) 
 
HTML(resum1, file=salida) 
 
HTML("&lt;p align=center&gt;Clientes por rango de edad&lt;/p&gt;") 
 
HTML("&lt;img src='c:\\temp\\informes\\resum1.png'&gt;&lt;/img&gt;") 
 
HTML("&lt;p align=center&gt;Estudio por saldo a la vista&lt;/p&gt;" ,file=salida) 
 
HTML(resum2, file=salida) 
 
HTML("&lt;p align=center&gt;Clientes por saldo a la vista&lt;/p&gt;") 
 
HTML("&lt;img src='c:\\temp\\informes\\resum2.png'&gt;&lt;/img&gt;") 
 
HTML("&lt;/div&gt;") 
 
HTMLEndFile()</em>

El objeto salida es una página estática HTML que llama a una hoja de estilos, con esto podemos realizar tablas más bonitas y espectaculares. Esta página se crea con la función HTMLInitFile, con la función HTML ya introducimos código HTML a salida hasta que encontramos HTMLEndFile. Yo no soy ningún experto en HTML, creo que sería mejor decir que no tengo ni idea pero con Google y R2HTML vamos a crear informes tan bonitos como este.