3 Visualizaciones de datos en R

Al terminar este capítulo ustedes van a poder:
- Entender la sintáxis usada por ggplot
- Hacer gráficos de dispersión de puntos y de líneas 
- Modificar los valores predeterminados de las paletas de colores, etiquetas, títulos, entre otros elementos de los gráficos
- Exportar los gráficos con calidad de publicación
- Animar y exportar animaciones de gráficos

3.1 La importancia de la visualización de los datos

La visualización de datos ha ganado espacio en diversas publicaciones y en las últimas décadas ya constituye una disciplina en sí misma. Su relevancia podría justificarse de muchas maneras, pero hay un punto que es especialmente relevante para el análisis de datos: los parámetros y coeficientes con los que solemos trabajar no siempre son tan simples de interpretar como pensamos. Por ejemplo, algunos autores recomiendan fuertemente graficar las predicciones del modelo ante distintos valores, antes que los coeficientes del modelo (McElreath, 2016).

Este punto dista de ser uno moderno. En 1973 el estadístico Francis Anscombe aportó la siguiente evidencia sobre cómo muchas de las variables que solemos tomar como de resumen, o incluso de relación entre ellas, puede engañarnos si no visualizamos correctamente los datos:

Si prestan atención, van a poder ver que la nube de puntos de cada uno de los datasets es bien distinta. El primero de arriba a la izquierda parece un scatter plot alrededor de una media, que podría modelarse linealmente. El segundo, el de arriba a la derecha, parecería tener una relación más cuadrática. El tercero, el de abajo a la izquierda, muestra una relación linea aparentemente con baja volatilidad, pero un punto bien alejado de esa recta, mientras que el último muestra casi ninguna relación entre x e y, con la excepción de un punto muy alejado del resto.

¿Pero que sucede cuando trazamos una línea que minimiza la distancia cuadrática entre los puntos? La recta (azul) es ¡la misma! ¿Y qué pasa con los promedios de las variables y la correlación entre ellas? También son iguales:

## # A tibble: 4 x 4
##   dataset   promedioX promedioY corXY
##   <chr>         <dbl>     <dbl> <dbl>
## 1 Dataset 1         9      7.50 0.816
## 2 Dataset 2         9      7.50 0.816
## 3 Dataset 3         9      7.5  0.816
## 4 Dataset 4         9      7.50 0.817

De esta manera queda en claro que, en algunas ocasiones, trabajar con resumenes de nuestros datos puede llevarnos a extraer conclusiones erróneas sobre cómo deberíamos analizarlos.

Durante los años se fue mejorando este punto que hizo Anscombe y… ahora sabemos que una nube de puntos que se parece a un dinosauro: si nos guiamos solo por las clásicas medidas de resumen, son indistinguibles

3.2 GGPLOT: Grammar of Graphics

Cuando se trata de hacer visualizaciones en R, ggplot es, por lejos, nuestro principal aliado y la librería más ampliamente difundida. Este paquete viene incluido dentro de tidyverse, por lo que cargando dicho paquete ya van a contar con todas sus funciones.

Con ggplot podemos crear decenas de distintos tipos de gráficos mediante una sintáxis unificada, lo que hace que se ganen importante economías de escala, una vez superada la curva de aprendizaje.

library(tidyverse)

3.3 ¿Cuál es la relación entre el ingreso de un país y la expectativa de vida al nacer? Scatterplot

Una nube de puntos o scatter plot es un tipo de gráfico que, por lo general, muestra la relación entre dos variables. Digo por lo general, porque en rigor es posible agregar otra información en estos gráficos mediante colores o tamaños de los puntos. Sigamos con el ejemplo del capitulo dos: los datos de gapminder. Vamos a filtrar los datos para el año 2007, el último en este dataset.

gapminder_df <- read.table(file = "https://raw.githubusercontent.com/martintinch0/CienciaDeDatosParaCuriosos/master/data/gapminder.csv",
                           sep=';',
                           header = TRUE,
                           stringsAsFactors = FALSE)
gapminderLastCut <- gapminder_df %>% filter(year==2007)

Ya podemos comenzar con nuestro primer ejemplo. ggplot comienza siempre dela misma manera: usando la función homónima y comentando que datos queremos graficar. Luego, le decimos qué tipo de gráfico queremos hacer, lo que en GG se hace con geom_, seguido por un sufijo que hace referencia específica al tipo de gráfico.

Además, GGPLOT no hace magia: en este caso, necesita saber qué variable poner en el eje x y cuál otra poner en el eje y. En ggplot, estas últimas indicaciones van dentro de una función que se llama aes(), que es la abreviación de aesthetics.

ggplot(data = gapminderLastCut,
       mapping = aes(x=gdpPercap, y = lifeExp)) +
  geom_point()

Nuestro gráfico scatter, que en ggplot se hace con geom_point(), muestra en el eje horizontal el PIB per cápita de los países y en el eje vertical la expectativa de vida al nacer. La grilla de fondo de color gris y los títulos de los ejes son defaults de ggplot, así como la - no tan recomendada - decisión de cortar al eje vertical en un valor levemente superior a 40 años.

Una vez que tenemos los datos que queremos en nuestro gráfico, podemos empezar a cambiar estos detalles que pueden no gustarnos. Para empezar, los títulos de los ejes tienen por definición el nombre de las variables, vamos a ponerles nombres más acordes a lo que estamos mostrando. Como irán aprendiendo, estos cambios van en distintas partes de nuestro código de ggplot mediante nuevas funciones agregadas por medio de +:

ggplot(data = gapminderLastCut,
       mapping = aes(x=gdpPercap, y = lifeExp)) +
  geom_point() +
  labs(x = "PIB per cápita",
       y = "Expectativa de vida al nacer (en años)")

En este caso usamos la función labs(), con sus respectivos parámetros x e y, a los que les pasamos directamente el nombre que queremos que tenga. La función labs permite más cosas que esto, como agregar título, subtítulos e incluso información sobre la fuente de nuestro gráfico:

ggplot(data = gapminderLastCut,
       mapping = aes(x=gdpPercap, y = lifeExp)) +
  geom_point() +
  labs(x = "PIB per cápita",
       y = "Expectativa de vida al nacer (en años)",
       title="A más ingresos mayor tiempo de vida?",
       subtitle="Expectativa de vida al nacer según nivel de ingreso",
       caption="Fuente: Gapminder")

3.3.1 Agregando colores según otras variables

En nuestro data.frame de gapminder contamos con otra variable que sería de interés mostrar: el continente del país que hablamos. Esta variable es de tipo categórica y es muy común agregar esta clase de variables en nuestros gráficos de dispersión o scatter plots

Agregar esta clase de información es realmente fácil. Dentro de la función aes(), además de determinar cuáles son los valores del eje vertical (y) y del eje horizontal (x), podemos indicar cuál es la variable según la cual queremos que ponga los colores: mediante el argumento color

ggplot(data = gapminderLastCut,
       mapping = aes(x=gdpPercap, y = lifeExp,color=continent)) +
  geom_point() +
  labs(x = "PIB per cápita",
       y = "Expectativa de vida al nacer (en años)",
       title="A más ingresos mayor tiempo de vida?",
       subtitle="Expectativa de vida al nacer según nivel de ingreso",
       caption="Fuente: Gapminder")

Podemos observar cómo los colores no se distribuyen aleatoriamente entre niveles de ingreso, sino que se ubican más o menos en los mismos rangos, con algunas excepciones. Más adelante vamos a ver un gráfico que nos va a ser útil para detectar estás diferencias.

3.4 ¿Cuál fue la evolución de la expectativa de vida al nacer? Gráfico de líneas

Otro de los gráficos más simples consiste en analizar la evolución de una determinada variable en el tiempo mediante una línea de tiempo. En ggplot estos gráficos pueden crearse usando geom_line.

Digamos que queremos observar la evolución de la expectativa de vida al nacer promedio por continente. Usando las herramientas de tidyverse podemos generar este promedio de la siguiente manera:

promedioContinente <- gapminder_df %>%
                      group_by(continent,year) %>%
                      summarise(promedio=mean(lifeExp))

Luego, ya estamos en condiciones de hacer el gráfico:

ggplot(data = promedioContinente,
       mapping = aes(x=year, y = promedio,color=continent)) +
  geom_line() +
  labs(x = "",
       y = "Expectativa de vida al nacer (en años)",
       title="Expectativa de vida al nacer según continente",
       caption="Fuente: Gapminder")

Ahora que hicimos nuestro gráfico de líneas, presten atención a dos puntos. Por un lado, cuando usamos el parámetro color en combinación con geom_line() ggplot entiende que esa variable debe ser la que corta a los datos, y los valores de cada una de ellas debe ser graficada por separada.

Por otro lado, y en relación al anterior punto, ggplot genera de manera automática una leyenda que nos permite unir el color de la variable por la que abrimos a los datos y su categoría. Veamos cómo cambiar la apariencia de la leyenda, lo que nos llevará a conocer otras funciones importantes de ggplot.

Si al intentar hacer este gráfico se decepcionaron al ver que no ven ninguna línea, no se preocupen. Miren la consola y lean si no está el siguiente mensaje:
geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?

En caso de ser así, lo que sucede es que ggplot agrupa de manera predeterminada a aquellas variables que no son numéricas. Como dos de las tres variables que están usando son de tipo charactere, entonces ggplot las agrupa y hay un problema al hacer líneas: necesitamos al menos dos puntos para hacer una línea.

Tenemos dos soluciones. La primera consiste en convertir a alguna de las variables que están como caracteres (por ejemplo, es posible que tengan la variable year como character). La segunda solución es usar el argumento group dentro de la función aes(), este argumento explicita por cual variable queremos agrupar, por lo que desactivamos la acción que tiene ggplot de manera determinada. Hay un ejercicio al final de este capítulo que repasa este punto.

3.4.1 Cambiando la apariencia de las leyendas

Para modificar la presentación de la leyenda podemos usar distintas funciones. Imaginen que deseamos cambiar el título de la leyenda. Esto se hace simplemente con una leve modificación dentro de la función labs(), agregando un parámetro que haga referencia al aesthetic que mapearon. En este caso, corresponde color:

ggplot(data = promedioContinente,
       mapping = aes(x=year, y = promedio,color=continent)) +
  geom_line() +
  labs(x = "",
       y = "Expectativa de vida al nacer (en años)",
       title="Expectativa de vida al nacer según continente",
       caption="Fuente: Gapminder",
       color ='Continente')

Muchas veces también queremos cambiar el lugar en el que está la leyenda, o quizás su dirección (puede estar de manera vertical, como en el ejemplo, u horizontal). Pero antes de mostrar cómo hacer esto, vamos a ver que podemos guardar gráficos de ggplot como objetos:

graficoLinea <- ggplot(data = promedioContinente,
       mapping = aes(x=year, y = promedio,color=continent)) +
  geom_line() +
  labs(x = "",
       y = "Expectativa de vida al nacer (en años)",
       title="Expectativa de vida al nacer según continente",
       caption="Fuente: Gapminder",
       color ='Continente')
# Si ejecutan la siguiente línea va a devolver el gráfico 
# graficoLinea

Esta funcionalidad nos va a servir tanto como para ir agregando “capas” a nuestro gráfico como para exportar nuestros gráficos, como veremos posteriormente. Ahora, modifiquemos de lugar a la leyenda usando la función theme()

graficoLinea + theme(legend.position = "bottom")

# graficoLinea + theme(legend.position = "top")

Con la función theme() podemos cambiar todos aquellos aspectos que no tengan que ver con el contenido, sino con las formas, tamaños y disposiciones de nuestros objetos, veremos más opciones de esto cuando queramos guardar nuestros gráficos. Muchas veces no queremos agregar las leyendas, que por default ggplot las muestra ¿Cómo evitamos que se muestren? con legend.position=“none”.

Otra clásica situación es querer cambiar el orden de la leyenda. Por default ggplot usa el orden que tenga la variable factor (categórica) por la que estamos abriendo a los datos. Si bien podemos cambiar este orden en las variables originales, suele ser una mejor idea modificarlas específicamente para el gráfico.

Esto lo podemos hacer con scale_color_manual. Esta función en rigor define información relevante para la paleta y su relación con los colores. Los breaks los valores que la leyenda puede tomar, mientras que en values directamente debemos indicar los colores para cada uno de estos valores en el sistema hexadecimal. Vean el siguiente ejemplo:

graficoLinea + 
  scale_color_manual(breaks=c("Europe","Asia","Oceania","Africa","Americas"),
                       values = c("#E41A1C","#377EB8","#4DAF4A" ,"#984EA3","#FF7F00"))

Vean cómo ahora el orden de las leyendas se desplegan según la secuencia que nosotros queríamos y los colores han cambiado de acauerdo a nuestro vector values ¿De dónde elegí esos colores? De las muy buenas paletas de colores que ofrece el paquete RColorBrewer y que pueden explorar acá o mediante el siguiente código, una vez que lo hayan instalado:

library(RColorBrewer)
display.brewer.all()

Como pueden ver el paquete cuenta con un conjunto de paletas que son útiles en diversas situaciones. En este caso, los cinco colores que usé en el gráfico anterior pertenecen a la paleta set1. Generar estos vectores es muy simple, solo tenemos que usar la función brewer.pal() con la cantidad de colores a generar y la paleta desde donde obtenerlos

brewer.pal(n = 5,name = "Set1")
## [1] "#E41A1C" "#377EB8" "#4DAF4A" "#984EA3" "#FF7F00"

3.5 Reproduciendo el gráfico de Hans Rosling

Ahora que ya introdujimos algunos de los gráficos más usados estamos en condiciones de reproducir uno de los gráficos de Rosling para el año 2007. En el camino, vamos a introducir algunos puntos básicos y relevantes de ggplot.

Recuerden que en gapminderLastCut tenemos los datos pertenecientes al último año de nuestro dataset, 2007. Trabajaremos con estos datos, agregando capas de a una a la vez y aclarando, en los comentarios, para que sirven:

# Definición de los datos a graficar y de qué mostrar en
# cada aesthetic
gapminder2007 <- ggplot(data = gapminderLastCut,
       mapping = aes(x = gdpPercap,
                     y = lifeExp,
                     color=continent,
                     size=pop))
# Tipo de gráfico a hacer
gapminder2007 <- gapminder2007 + geom_point()
# ¿Qué leyendas mostrar? No mostrar aquella relacionada con el tamaño. Prueben qué pasa si no agregan esto al gráfico
gapminder2007 <- gapminder2007 + guides(size=FALSE)
# Elegimos un tema preestablecido, en este caso *minimal*
gapminder2007 <- gapminder2007 + theme_minimal()
# El eje x, que tiene una variable continua, queremos que muestre
# los datos en logaritmos para evitar que los puntos se "junten"
# muy cerca del inicio y no nos permitan ver los cambios
gapminder2007 <- gapminder2007 + scale_x_continuous(trans = 'log10')
gapminder2007

Hemos agregado un par de funciones más que vale la pena aclarar. En primer lugar, el uso de la función guides(), que entre otras cosas es útil para elegir qué leyendas queremos que aparezcan en nuestro gráfico y qué no. Por definición, cada aesthetic que agregamos (color, tamaño, símbolo) tiene un correlato en la leyenda. Pero en nuestro caso no queremos que muestre los tamaños con un determinado tamaño de población: basta con saber que mientras más grande es el tamaño de la bola, más alta es la población del país. Para eso agregamos guides(size=FALSE)

En segundo lugar, incluimos theme_minimal(). Esta función, así como todas las que comienzan con theme_ son un conjunto de código que iría dentro de theme() y que nos permiten generar estilos preestablecidos de una manera muy simple. Minimal, por ejemplo, elimina el fondo gris con rayas blancas que es lo predeterminado en ggplot. Escriban “theme” y luego presionen tab en RStudio y verán más opciones como theme_bw, theme_dark. Pruebenlos.

Finalmente, con scale_x_continuous() podemos transformar la presentación de los datos sin crear inncesariamente variables en nuestro data frame. En este caso queremos transformar los valores a logaritmo para evitar que las importantes diferencias en PIB per cápita entre los países no nos permitan ver variaciones relativas importantes entre los países de ingresos bajos y medios-bajos.

Ahora vamos a usar prácticamente todo lo aprendido en este capítulo para armar un gráfico que podremos exportar. A nuestro último gráfico le agregamos algunos detalles como la mejora de la leyenda, otros colores y distintos títulos.

gapminder2007 <- gapminder2007 + 
  scale_color_manual(breaks=c("Europe","Asia","Oceania","Africa","Americas"),
                     values = c("#E41A1C","#377EB8","#4DAF4A" ,"#984EA3","#FF7F00")) + 
    labs(x = "PIB per cápita",
       y = "Expectativa de vida al nacer (en años)",
       title="A más ingresos mayor tiempo de vida?",
       subtitle="Expectativa de vida al nacer según nivel de ingreso",
       color="Continente",
       caption="Fuente: Gapminder")

Si quieren ejecuten el objeto gapminder2007 para ver cómo quedó. Ahora iremos con la última parte de este capítulo: cómo exportar los gráficos que hacemos.

3.5.1 Exportando gráficos de ggplot

Exportar los gráficos es una tarea clave, y es realmente fácil con ggplot. Solo debemos usar la función ggsave:

ggsave(filename = "hansRosling2007.png",
       plot = gapminder2007,
       dpi = 300)

ggsave nos pide un nombre de archivo, y un gráfico a exportar. Luego, nosotros podemos incluir información sobre la calidad del gráfico o ciertos parámetros adicionales. DPI es la cantidad de Dot Per Inch (puntos por pulgadas) que queremos que tenga. Mientras mayor sea este número, mayor será la “calidad” del gráfico (y tendrá mayores píxeles y peserá más. Ejecuten el código, deberían tener algo similar a esto.

Primer gráfico exportado. Gapminder para el año 2007

Figure 3.1: Primer gráfico exportado. Gapminder para el año 2007

3.6 Mapas

En el capítulo 4 de este mismo libro introducimos a los datos espaciales. Allí vamos a analizar por qué requieren de un tratamiento especial tanto en el formato en el que están almacenados y su manera de representarse. En esta sección vamos a mostrar las capacidades que tiene el paquete ggplot para hacer mapas en R.

Vamos a trabajar con dos data frames, uno que contiene el precio de los inmuebles de la Ciudad de Buenos Aires como puntos, y otro que tiene el precio de los inmuebles promeido por barrio. Ambos data frame son, en realidad, objetos sf, que se ven en detalle en el capítulo 4.

library(sf)
preciosCABA <- read_sf('https://github.com/martintinch0/CienciaDeDatosParaCuriosos/raw/master/data/PreciosCABASample.geojson')
preciosCABABarrios <- read_sf('https://raw.githubusercontent.com/martintinch0/CienciaDeDatosParaCuriosos/master/data/PreciosCABABarrioYear.geojson')
proyeccionCenso2010 <- '+proj=tmerc +lat_0=-34.629717 +lon_0=-58.4627 +k=1 +x_0=100000 +y_0=100000 +a=6378388 +b=6378386.996621622 +towgs84=-148,136,90,0,0,0,0 +units=m +no_defs '
preciosCABA <- st_transform(preciosCABA,crs = proyeccionCenso2010)
preciosCABABarrios <- st_transform(preciosCABABarrios,crs = proyeccionCenso2010)

Una vez que ejecuten todo el código van a tener dos objetos nuevos: preciosCABA y preciosCABABarrios. El primero de ellos es una muestra estratificada por año y barrios (es decir que toma una muestra para cada uno de estos grupos) de los anuncios de ventas de inmuebles en la Ciudad de Buenos Aires, mientras que el segundo muestra la evolución por año del precio promedio en USD de los inmuebles ofertados.

Hacer un gráfico con objetos de clase sf es realmente fácil con ggplot, solo debemos agregar geom_sf. Imaginen que queremos graficar los avisos de todos los años:

ggplot() +
  geom_sf(data = preciosCABA, mapping = aes(color=PrecioM2))

¿Fácil, no? Y también muy poco estético, pero ya vamos a tener tiempo de corregirlo. Presten atención a la escala, aparecen todos los puntos en negro, excepto uno que aparece en azul claro, indicador de valor muy alto. Evidentemente existe algún valor extremo, y esto suele ser algo normal. Como nuestro objetivo es simplemente hacer gráficos, vamos a eliminar estos datos, pero no deberían hacerlo con tanta facilidad en sus investigaciones:

preciosCABA <- preciosCABA %>% filter(PrecioM2<10000 & PrecioM2>500)
ggplot() +
  geom_sf(data = preciosCABA, mapping = aes(color=PrecioM2))

Pareciera haber mejorado en algo, pero por ahora sigamos con nuestro ejercicio. Lo primero que querríamos hacer es eliminar ese fondo y, quizás, las cuadrículas y también la latitud y longitud que nos señalan los ejes. Lo primero lo podemos hacer usando algunos de los temas que vienen con ggplot, por ejemplo theme_minimal()

ggplot() +
  geom_sf(data = preciosCABA, mapping = aes(color=PrecioM2)) +
  theme_minimal()

Para eliminar las lineas de fondo y las referencias a la longitud y latitud solo debemos agregar coord_sf(datum = NA):

ggplot() +
  geom_sf(data = preciosCABA, mapping = aes(color=PrecioM2)) +
  theme_minimal() + coord_sf(datum = NA)

Mucho mejor. Sin embargo, si queremos mostrar el precio de las propiedades en el mapa según su valor debemos poner un contexto y también mejorar la escala. El Contexto serán los datos de polígonos que tenemos en el otro dataset, mientras que la escala intentaremos solucionarla usando la famosa paleta de viridis:

ggplot() +
  geom_sf(data=preciosCABABarrios, fill=NA) +
  geom_sf(data = preciosCABA, mapping = aes(color=PrecioM2)) + 
  scale_color_viridis_c() +
  theme_minimal() +
  coord_sf(datum = NA) 

Mucho mejor. Ahora bien, son muchos datos, qué tal si mostramos los distintos valores por año? Podemos hacer esto mediante la función facet_wrap():

ggplot() +
  geom_sf(data=preciosCABABarrios, fill=NA) +
  geom_sf(data = preciosCABA, mapping = aes(color=PrecioM2), size=0.5) +
  facet_wrap(facets = ~ Year) + 
  scale_color_viridis_c() +
  theme_minimal() +
  coord_sf(datum = NA)

Por lo visto, los valores de los precios se encuentran sesgados hacia la derecha (valores altos), lo que no nos permite visualizar correctamente los valores en los mapas. Creemos una variable categórica de los precios y veamos si mejora.

preciosCABA<-preciosCABA %>%
  ungroup %>%
  mutate(PrecioM2Cat = cut(PrecioM2,quantile(PrecioM2), include.lowest = TRUE))
ggplot() +
  geom_sf(data=preciosCABABarrios, fill=NA) +
  geom_sf(data = preciosCABA, mapping = aes(color=PrecioM2Cat,fill=PrecioM2Cat), size=0.5) +
  facet_wrap(facets = ~ Year) + 
  scale_color_viridis_d() +
  scale_fill_viridis_d() +
  theme_minimal() +
  coord_sf(datum = NA) +
  labs(fill="Precios",color="Precios")

En la primera parte creamos la categoría de la variable con la función cut(), que recibe 1) un conjunto de valores, 2) un vector con puntos de quiebre y nos devuelve un factor que dice en cada cual de esos segmentos caen los valores. Aunque lo hace muy bien, casi nunca nos gusta los labels que asigna, es decir las etiquetas que corresponden a cada nivel. Existen muchas formas de cambiar esto, una deellas es usando la función level(). Lo único que hay que hacer es pasarle los nuevos valores que deben reemplazar a los viejos. Veamos, primero, que devuelve la función:

levels(preciosCABA$PrecioM2Cat)
## [1] "[503,1.51e+03]"      "(1.51e+03,2e+03]"    "(2e+03,2.55e+03]"    "(2.55e+03,9.71e+03]"

Ahora ya podemos reemplazar estos valores por algunos que nos parezcan más razonables. Veamos los valores de quiebre y creemos una mejor leyenda:

round(quantile(preciosCABA$PrecioM2),0)
##   0%  25%  50%  75% 100% 
##  503 1513 2000 2550 9706
nuevosLabels <- c('De 503 a 1500', 'De 1501 a 1987', 'De 1988 a 2500','Más de 2500')
levels(preciosCABA$PrecioM2Cat) <- nuevosLabels

Además de esto, vamos a ponerle un título y un subtítulo para agregar más información a nuestro mapa:

ggplot() +
  geom_sf(data=preciosCABABarrios, fill=NA) +
  geom_sf(data = preciosCABA, mapping = aes(color=PrecioM2Cat,fill=PrecioM2Cat), size=0.5) +
  facet_wrap(facets = ~ Year) + 
  scale_color_viridis_d() +
  scale_fill_viridis_d() +
  theme_minimal() +
  coord_sf(datum = NA) +
  labs(fill="Precios",color="Precios",title="Evolución de precios de los inmuebles en CABA",subtitle='2015-2019')

3.6.1 Mapas animados

A veces, mostrar muchos mapas estáticos no comunica tan bien como hacerlo de una manera animada. El paquete gganimate nos permite usar prácticamente la misma sintáxis de ggplot para hacer animados a nuestros mapas. Hagamos uno que muestre los precios de los inmuebles por año para cada barrio de la Ciudad de Buenos Aires:

library(gganimate)
preciosCABABarrios<-preciosCABABarrios %>%
  mutate(PrecioM2Cat = cut(PrecioM2,quantile(PrecioM2), include.lowest = TRUE))
levels(preciosCABABarrios$PrecioM2Cat) <- c('De 761 a 1661', 'De 1662 a 1973', 'De 1974 a 2319', 'Más de 2320')

ggplot(data = preciosCABABarrios, mapping = aes(fill=PrecioM2Cat)) +
  geom_sf(color='white') +
  guides(size=FALSE) +
  theme_minimal() +
  coord_sf(datum = NA) +
  scale_fill_viridis_d() +
   labs(title = "Mapa de precios de inmuebles en CABA",
       y = "",
       subtitle="Año: {current_frame}",
       fill="Categoría de precios",
       caption="Fuente: Properati Data") +
  transition_manual(Year)
## Warning: No renderer available. Please install the gifski, av, or magick package to create animated output
## NULL

3.7 Ejercicios

Descarguen el dataset de precios de los inmuebles que pueden obtener desde el siguiente link, que lo pasaremos a formato largo y eliminaremos el sufijo USDm2_ para los precios de cada año.

precioAvisos <- read.csv(file = 'https://raw.githubusercontent.com/martintinch0/CienciaDeDatosParaCuriosos/master/data/precioBarrios.csv',
         sep=';',
         stringsAsFactors = FALSE)

precioAvisos<-precioAvisos %>% pivot_longer(cols = -BARRIOS,
                                            names_to= "Year",
                                            values_to='Valor'
                                            ) %>%
              mutate(Year=gsub(pattern = "USDm2_*",
                              replacement = "",
                              x = Year))

Ahora hagan los siguientes gráficos. En cada uno de ellos prueben con distintos colores y themes. Prueben instalar el paquete ggthemes y usar algunos de sus themes, como por ejemplo theme_fiverthirtyeight().

  1. Un gráfico de linea de tiempo que muestre la evolución de los precios entre 2013 y 2017 para los barrios de Agronomia, Almagro, Caballito y Coghlan ¿Pueden hacer este gráfico sin usar el argumento group? Revisen las variables de preciosAvisos y piensen la respuesta y las posibles soluciones.
  2. Un scatter plot para el precio (eje vertical) por año (eje horizontal)
  3. ¿Qué pasa si en el punto 2 usan geom_boxplot en lugar de geom_point? Recuerden que para hacer un boxplot es preciso tener más de un punto por grupo que se muestra, ya que resume la distribución de un conjunto de puntos.

3.8 Extensión: animando el gráfico de Hans Rosling

El gráfico original de Hans Rosling muestra la evolución en el tiempo de las dos variables a lo largo del tiempo. Con el paquete gganimate solo debemos agregar dos líneas de código - y modificar levemente otras dos - para tener el gráfico que buscamos.

En primer lugar, si queremos mostrar la evolución en el tiempo de estas variables tenemos que usar el data frame completo, no solo la última foto.

En segundo lugar, debemos indicar cuáles son los quiebres en nuestro eje horizontal, porque en caso de no hacerlo R va a expresar algunos cortes con notación científica. Esto lo hacemos dentro de scale_x_continuous, donde podemos incluir, dentro de breaks, los valores que queremos que muestre.

En tercer lugar, tenemos que indicarle a ggplot que se trata de una animación. Esto lo hacemos con transition_time(year), en donde le indicamos cual es la variable por la cual tiene que hacer la transición de las fotos. Además le decimos que, cómo hay baches entre los años, los complete con una interpolación lineal con el siguiente código ease_aes(‘linear’)

Finalmente modificamos el título del gráfico con Año: {frame_time} para que nos vaya indicando el año que estamos viendo en la animación.

library(gganimate)
gapminderAnim <- ggplot(data = gapminder_df,
                        mapping = aes(x = gdpPercap,
                                      y = lifeExp,
                                      color=continent,
                                      size=pop)) +
  geom_point() +
  guides(size=FALSE) +
  theme_minimal() +
  scale_x_continuous(trans = 'log10',breaks = c(1000,10000,70000)) +
  scale_color_manual(breaks=c("Europe","Asia","Oceania","Africa","Americas"),
                       values = c("#E41A1C","#377EB8","#4DAF4A" ,"#984EA3","#FF7F00")) + 
    labs(x = "PIB per cápita",
         y = "Expectativa de vida al nacer (en años)",
         title="Año: {frame_time}",
         subtitle="Expectativa de vida al nacer según nivel de ingreso",
         color="Continente",
         caption="Fuente: Gapminder") +
  transition_time(year) + 
  ease_aes('linear')

Si lo ejecutan, deberían tener algo similar a lo que se ve abajo:

Aunque para generar esta animación use anim_save(), el equivalente a ggsave(), pero para animaciones:

anim_save(filename="animacion.gif",
          animation = gapminderAnim,
          width=2100,
          height=1500,
          res=300)