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_inisaldo_ppi=(edad<65)*datos_inisaldo_ppi
#Creamos la variable objetivo a partir de un potencial
datos_inipotencial= runif(clientes,0,1)
datos_inipotencial= datos_inipotencial +
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_inipvi=(datos_inipotencial>=quantile(datos_inipotencial,
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_inirango_edad <- recode(datos_iniedad,
"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_inirango_vista <- recode(datos_inisaldo_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íasplyr 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))
resum1tasa=fmt.porcen(resum1contrata*100/resum1clientes)
resum1clientes=sep.miles(resum1clientes)
resum1contrata=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))
resum2tasa=fmt.porcen(resum2contrata*100/resum2clientes)
resum2clientes=sep.miles(resum2clientes)
resum2contrata=sep.miles(resum2$contrata)
```r
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\:
```r
library(R2HTML)
salida = HTMLInitFile( "C:\\temp\\informes",filename="salida",
CSSFile="C:\\TEMP\\informes\\table_design.css")
HTML("<div align=center>")
HTML("<p align=center>Estudio por edad</p>" ,file=salida)
HTML(resum1, file=salida)
HTML("<p align=center>Clientes por rango de edad</p>")
HTML("<img src='c:\\temp\\informes\\resum1.png'></img>")
HTML("<p align=center>Estudio por saldo a la vista</p>" ,file=salida)
HTML(resum2, file=salida)
HTML("<p align=center>Clientes por saldo a la vista</p>")
HTML("<img src='c:\\temp\\informes\\resum2.png'></img>")
HTML("</div>")
HTMLEndFile()
```
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](/images/2011/11/informes/salida.html).