Introducción práctica a la librería ggplot2 y su integración con ggmap

Roger Borràs, Lluís Ramon, Andreu Vall

Barcelona, noviembre 2012


Quién somos

Contenidos


Por qué usar ggplot2?

Qué es Grammar of graphics y los componentes de ggplot2

Requisitos de ggplot2


La BD de ejemplo

##  [1] "id"                 "country_code"       "country_name"      
##  [4] "continent"          "region"             "income_group"      
##  [7] "year"               "ease_of_business"   "foreign_investment"
## [10] "gdp"                "gni_per_capita"     "population"

De plot a qplot

El diagrama de dispersión

plot(climate_2010$ease_of_business, climate_2010$gni_per_capita)

plot of chunk Gràfic de dispersio base

El mismo gráfico con qplot de ggplot2

qplot(climate_2010$ease_of_business, climate_2010$gni_per_capita)

plot of chunk Grafic de dispersio amb qplot


Gráfico con modificación de las etiquetas y los límites de los ejes

qplot(ease_of_business, gni_per_capita, xlab = "EASE OF BUSINESS", ylab = "GNI PER CAPITA ($)", 
    xlim = c(0, 200), size = I(4), data = climate_2010)

plot of chunk Modifiacio limits i eixos amb qplot


El ejemplo por continentes:

climate_africa <- subset(climate_2010, continent == "AFRICA")
climate_asia <- subset(climate_2010, continent == "ASIA")
climate_europa <- subset(climate_2010, continent == "EUROPE")
climate_namerica <- subset(climate_2010, continent == "N.AMERICA")
climate_oceania <- subset(climate_2010, continent == "OCEANIA")
climate_samerica <- subset(climate_2010, continent == "S.AMERICA")

plot(climate_africa$ease_of_business, climate_africa$gni_per_capita, pch = 16, 
    col = "red", ylim = c(0, 90000), xlab = "EASE OF BUSINESS", ylab = "GNI PER CAPITA ($)")
points(climate_asia$ease_of_business, climate_asia$gni_per_capita, pch = 16, 
    col = "blue")
points(climate_europa$ease_of_business, climate_europa$gni_per_capita, pch = 16, 
    col = "green")
points(climate_namerica$ease_of_business, climate_namerica$gni_per_capita, pch = 16, 
    col = "magenta")
points(climate_oceania$ease_of_business, climate_oceania$gni_per_capita, pch = 16, 
    col = "yellow")
points(climate_samerica$ease_of_business, climate_samerica$gni_per_capita, pch = 16)
legend(150, 85000, c("AFRICA", "ASIA", "EUROPA", "N.AMERICA", "OCEANIA", "S.AMERICA"), 
    col = c("red", "blue", "green", "magenta", "yellow", "black"), pch = c(16, 
        16, 16, 16, 16, 16))

plot of chunk Dispersio per continents base

Con ggplot2 el gráfico tiene una sintaxis mas simple y clara:

qplot(ease_of_business, gni_per_capita, colour = continent, data = climate_2010, 
    xlab = "EASE OF BUSINESS", ylab = "GNI PER CAPITA ($)")

plot of chunk Dispersio per continents amb qplot


Modificación con leyenda tipo shape

qplot(ease_of_business, gni_per_capita, shape = continent, xlab = "EASE OF BUSINESS", 
    ylab = "GNI PER CAPITA ($)", data = climate_2010)

plot of chunk Dispersio amb modifiacio shape

Modificación con leyenda tipo shape y colour

qplot(ease_of_business, gni_per_capita, shape = continent, colour = continent, 
    xlab = "EASE OF BUSINESS", ylab = "GNI PER CAPITA ($)", data = climate_2010)

plot of chunk Dispersio amb modifiacio shape i colour

Definimos con geom, añadimos una regresión loess y lo guardamos en una variable:

p1 <- qplot(ease_of_business, gni_per_capita, geom = c("smooth", "point"), xlab = "EASE OF BUSINESS", 
    ylab = "GNI PER CAPITA ($)", data = climate_2010)
p1

plot of chunk Dispersio amb regressió loess


El gráfico de boxplot

p2 <- qplot(continent, ease_of_business, geom = c("boxplot"), fill = I("deepskyblue1"), 
    alpha = I(0.25), xlab = "CONTINENT", ylab = "EASE OF BUSINESS", data = climate_2010)
p2

plot of chunk Grafic boxplot amb qplot


El gráfico de densidad

p3 <- qplot(gni_per_capita, geom = c("density"), fill = I("gold"), alpha = I(0.85), 
    xlab = "GNI PER CAPITA ($)", ylab = "DENSITY", data = climate_2010)
p3

plot of chunk Grafic de densitat amb qplot


Los facets

p4 <- qplot(ease_of_business, gni_per_capita, facets = ~continent, ncol = 3, 
    xlab = "EASE OF BUSINESS", ylab = "GNI PER CAPITA ($)", data = climate_2010)
p4

plot of chunk Facets amb qplot


Integración de los gráficos en un mismo panel

library(gridExtra)
grid.arrange(p1, p2, p3, p4, ncol = 2)

plot of chunk Integracio panell


De qplot a ggplot

qplot nos da una sintaxis breve y parecida a plot.

climate_2010 <- subset(climate, year == 2010)
qplot(ease_of_business, gni_per_capita, geom = c("smooth", "point"), xlab = "EASE OF BUSINESS", 
    ylab = "GNI PER CAPITA ($)", data = climate_2010)

plot of chunk qplot: una linia


Sin embargo, el anterior gráfico se compone de varias capas.

qplot(ease_of_business, gni_per_capita, data = climate_2010) +  
  # geom_point() por defecto en qplot  
  geom_smooth() +  
  xlab("EASE OF BUSINESS") +  
  ylab("GNI PER CAPITA ($)")

plot of chunk qplot: diverses linies


O usando ggplot

ggplot(data = climate_2010, aes(x = ease_of_business, y = gni_per_capita)) +  
  geom_point() +       
  geom_smooth() +  
  xlab("EASE OF BUSINESS") +  
  ylab("GNI PER CAPITA ($)")

plot of chunk ggplot: com qplot diverses linies


¡Atención!

¿Diferencia en la sintaxis?

¿Diferencia en el uso?


Seguiremos trabajando con el gráfico de dispersión ease_of_business vs gni_per_capita.

p <- ggplot(data = climate_2010, aes(x = ease_of_business, y = gni_per_capita))
p + geom_point()

plot of chunk plot basic: ease_of_business vs gni_per_capita


Las geometrías

Las geometrías (geom) definen literalmente lo que vemos en el gráfico: puntos, lineas, polígonos, …

p1 <- p + geom_point()
p2 <- p + geom_line()
p3 <- p + geom_area()
grid.arrange(p1, p2, p3)

plot of chunk plot basic: canvi de geoms


Correspondencia vs asignación

p + geom_point(aes(color = continent))

plot of chunk diferencia assignar i correspondre

p + geom_point(color = "blue")

plot of chunk diferencia assignar i correspondre

# ¡atención!
p + geom_point(aes(color = "blue"))

plot of chunk diferencia assignar i correspondre


La leyenda

La leyenda se genera automáticamente a partir de las variables que definen una característica estética del gráfico (las que van dentro de la función aes).

p + geom_point(aes(color = continent))

plot of chunk llegenda: per defecte

p + geom_point(aes(color = continent, size = income_group))

plot of chunk llegenda: per defecte

p + geom_point(aes(color = continent, shape = continent, size = income_group))

plot of chunk llegenda: per defecte


Las funciones scale

Nos permiten controlar la correspondencia entre una variable y su representación gráfica.

p1 <- p + geom_point(aes(color = continent, size = income_group))
# leyenda generada automáticamente
p1

plot of chunk llegenda: modificacio de la llegenda

# edición del nombre las variables
p1 + scale_size_discrete("Income group") +
     scale_color_discrete("Continent")

plot of chunk llegenda: modificacio de la llegenda

# correspondencia entre la variable y su representación
p1 + scale_size_discrete("Income group", range = c(10,1)) +
     scale_color_brewer("Continent", palette = "Spectral")

plot of chunk llegenda: modificacio de la llegenda


**geom_line** y el uso de group

Vamos a analizar la evolución temporal del PIB de los países de Europa.

climate_europe <- subset(climate, continent == "EUROPE")

ggplot(climate_europe, aes(x = year, y = gdp/population)) +
  geom_line()

plot of chunk grafic linia: error no fer servir group


¡Atención!

Un solo elemento gráfico puede contener uno o muchos datos. Por ejemplo:

Con group controlamos qué observaciones pertenecen a cada elemento gráfico individual.


Usando group

ggplot(climate_europe, aes(x = year, y = gdp/population)) +
  geom_line(aes(group = country_code))

plot of chunk grafic linia: error arreglat fent servir group


Comprobamos la distribución de acuerdo con la variable income_group.

ggplot(climate_europe, aes(x = year, y = gdp/population)) +
  geom_line(aes(group = country_code, color = income_group))

plot of chunk grafic linia: distribucio per income_group

Añadimos una aproximación para cada grupo. Atención al uso de group diferente en cada capa del gráfico!

ggplot(climate_europe, aes(x = year, y = gdp/population)) +
  geom_line(aes(group = country_code, color = income_group)) +
  geom_smooth(aes(group = income_group, colour = income_group), size = 2)

plot of chunk grafic linia: aproximacio per cada grup


**geom_tile** y la edición manual de la leyenda

Estudiamos la inversión extranjera en cada país. Para simplificar, seleccionamos unos cuantos países europeos.

countries <- c("Finland", "Germany", "Italy", "Netherlands", "Greece")
climate_countries <- subset(climate_europe, country_name %in% countries)

ggplot(climate_countries, aes(x = year, y = foreign_investment)) +
  geom_line(aes(color = country_code, group = country_code))

plot of chunk grafic tile: subset de paisos


También podemos representar la altura de las ordenadas mediante un mapa de calor.

# atención al valor NA de Grecia
p <- ggplot(climate_countries, aes(x = year, y = country_code))
p + geom_tile(aes(fill = foreign_investment))

plot of chunk grafic tile: calor


Queremos representar el año de máxima inversión extranjera para cada país. Podemos calcular esta información y representarla en el gráfico.

max_investment <- function(df){
  max_investment <- rep("no_max", nrow(df))
  max_investment[which.max(df$foreign_investment)] <- "max"
  result <- data.frame(df, max_investment)
  return(result)
}

climate_countries <- ddply(climate_countries, .(country_code), max_investment)

head(climate_countries)
##     id country_code country_name continent                region
## 1 1043          DEU      Germany    EUROPE Europe & Central Asia
## 2 1044          DEU      Germany    EUROPE Europe & Central Asia
## 3 1045          DEU      Germany    EUROPE Europe & Central Asia
## 4 1046          DEU      Germany    EUROPE Europe & Central Asia
## 5 1047          DEU      Germany    EUROPE Europe & Central Asia
## 6 1048          DEU      Germany    EUROPE Europe & Central Asia
##        income_group year ease_of_business foreign_investment      gdp
## 1 High income: OECD 1990               NA               0.18 1.71e+12
## 2 High income: OECD 1991               NA               0.26 1.81e+12
## 3 High income: OECD 1992               NA              -0.10 2.06e+12
## 4 High income: OECD 1993               NA               0.02 2.00e+12
## 5 High income: OECD 1994               NA               0.34 2.15e+12
## 6 High income: OECD 1995               NA               0.48 2.52e+12
##   gni_per_capita population max_investment
## 1          20630   79433000         no_max
## 2          22170   80014000         no_max
## 3          25050   80624000         no_max
## 4          25200   81156000         no_max
## 5          26590   81516000         no_max
## 6          28630   81642000         no_max

# actualizar los datos de p
p <- p %+% climate_countries

Para visualizar el año de máxima inversión usamos color (con geom_tile, se trata del color del borde).

p +  geom_tile(aes(fill = foreign_investment, color = max_investment))

plot of chunk Grafic tiles: complet sense llegenda editada


Editamos manualmente la leyenda para conseguir unos colores fáciles de distinguir.

p + geom_tile(aes(fill = foreign_investment, color = max_investment)) + 
  scale_fill_gradient(low = "white", high = "red") +
  scale_color_manual(breaks = c("max","no_max"), values = c("darkblue","white"))

plot of chunk Grafic tiles: complet amb llegenda editada


Ejemplos de mapas con ggplot2

Geometría de polígonos

library(ggplot2)
library(maptools)
data(wrld_simpl)
is(wrld_simpl)
## [1] "SpatialPolygonsDataFrame" "SpatialPolygons"         
## [3] "Spatial"                  "SpatialPolygonsNULL"
head(wrld_simpl@data)
##     FIPS ISO2 ISO3 UN                NAME   AREA  POP2005 REGION SUBREGION
## ATG   AC   AG  ATG 28 Antigua and Barbuda     44    83039     19        29
## DZA   AG   DZ  DZA 12             Algeria 238174 32854159      2        15
## AZE   AJ   AZ  AZE 31          Azerbaijan   8260  8352021    142       145
## ALB   AL   AL  ALB  8             Albania   2740  3153731    150        39
## ARM   AM   AM  ARM 51             Armenia   2820  3017661    142       145
## AGO   AO   AO  AGO 24              Angola 124670 16095214      2        17
##         LON    LAT
## ATG -61.783  17.08
## DZA   2.632  28.16
## AZE  47.395  40.43
## ALB  20.068  41.14
## ARM  44.563  40.53
## AGO  17.544 -12.30
# fortify sirve con objetos maps, sp, etc
world_ggmap <- fortify(wrld_simpl, region = "ISO3")
head(world_ggmap)
##     long   lat order  hole piece group  id
## 1 -69.88 12.41     1 FALSE     1 ABW.1 ABW
## 2 -70.06 12.54     2 FALSE     1 ABW.1 ABW
## 3 -70.06 12.63     3 FALSE     1 ABW.1 ABW
## 4 -69.88 12.41     4 FALSE     1 ABW.1 ABW
## 5  74.92 37.24     5 FALSE     1 AFG.1 AFG
## 6  74.39 37.18     6 FALSE     1 AFG.1 AFG
ggplot(data = world_ggmap, aes(x = long, y = lat, group = group)) + geom_polygon()

plot of chunk ejemplo geom_polygon: grafico

Para representar información de climate seria necesario cruzar los datos de world_ggmap y climate.


Geometría de mapas

geom_map: usa geom_polygon, mucho más rápida y cruza los datos de mapa con la información del data.frame

ggplot(climate_2010) +
  geom_map(aes(map_id = country_code), map = world_ggmap) +
  expand_limits(x = world_ggmap$long, y = world_ggmap$lat)

plot of chunk ejemplo geom_map

Congo no ha cruzado correctamente porque tienen diferentes identificadores


Podemos usar los aesthetics de climate_2010

climate_2010 <- subset(climate, year == 2010)
ggplot(climate_2010) +
  geom_map(aes(map_id = country_code, fill = continent), map = world_ggmap) +
  expand_limits(x = world_ggmap$long, y = world_ggmap$lat)

plot of chunk ejemplo continente


Nueva capa con nuevo data.frame

q <- ggplot(climate_2010) +
     geom_map(aes(map_id = country_code, fill = ease_of_business), map = world_ggmap) +
     expand_limits(x = world_ggmap$long, y = world_ggmap$lat)

q

plot of chunk mapa_con_ciudades

library(maps)
data(world.cities)
head(world.cities)
##                 name country.etc   pop   lat  long capital
## 1 'Abasan al-Jadidah   Palestine  5629 31.31 34.34       0
## 2 'Abasan al-Kabirah   Palestine 18999 31.32 34.35       0
## 3       'Abdul Hakim    Pakistan 47788 30.55 72.11       0
## 4 'Abdullah-as-Salam      Kuwait 21817 29.36 47.98       0
## 5              'Abud   Palestine  2456 32.03 35.07       0
## 6            'Abwein   Palestine  3434 32.03 35.20       0
q + geom_point(aes(long, lat), colour = "red", size = 0.3,  data = world.cities)