Capítulo 3 Gráficos - Parte I

R base dispone de comandos para realizar gráficos sencillos que muchas veces resulta útil cuando estamos trabajando y queremos realizar alguna visualización rápida.

data(iris)
str(iris)
## 'data.frame':    150 obs. of  5 variables:
##  $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
##  $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
##  $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
##  $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
##  $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
names(iris)
## [1] "Sepal.Length" "Sepal.Width"  "Petal.Length" "Petal.Width"  "Species"
attach(iris) # Permite usar nombre de varaibles sin anteponer nombre de la base de datos

# Igual que en Clase 01 pero mas estadisticas
tapply(Petal.Length, Species, summary)
## $setosa
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   1.000   1.400   1.500   1.462   1.575   1.900 
## 
## $versicolor
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    3.00    4.00    4.35    4.26    4.60    5.10 
## 
## $virginica
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   4.500   5.100   5.550   5.552   5.875   6.900
plot(Petal.Length,Petal.Width, col = "red", pch = 19, cex = 2)

plot(Petal.Length,Petal.Width, col = Species, pch = 15, cex = 1)

boxplot(Petal.Length)

boxplot(Petal.Length ~ Species)

boxplot(Petal.Length ~ Species, col=rainbow(3))

# breaks = Freedman-Diaconis rule
hist(Petal.Length, breaks = 'FD', prob = TRUE, main = "Petal Length", col = "bisque", xlab = "")

# Guardar el grafico
png("hist.png")
hist(Petal.Length, breaks = 'FD', prob = TRUE, main = "Petal Length", col = "bisque", xlab = "")
dev.off()
## png 
##   2

3.1 ggplot2

ggplot2 es un paquete R para producir gráficos estadísticos o de datos. A diferencia de la mayoría de los otros paquetes de gráficos, ggplot2 tiene una gramática subyacente, basada en Grammar of Graphics, que permite realizar gráficos combinando componentes independientes. En vez de limitarse a conjuntos de gráficos predefinidos, se pueden crear gráficos novedosos que se adapten a un problema específico. Si bien la idea de tener que aprender una gramática puede parecer abrumadora, ggplot2 es realmente fácil de aprender: hay un conjunto simple de principios básicos y hay muy pocos casos especiales.

ggplot(data = <DATA>) +                       # datos (que graficar)
  <GEOM_FUNCTION>(mapping = aes(<MAPPINGS>))  # aesthetics (como graficar)

OPCIONES
  labs()        # titulos
  theme()       # aspectos no relacionados con datos (leyendas)
  scales_*()    # escalas de los ejes
data(mpg)
str(mpg)
## tibble [234 × 11] (S3: tbl_df/tbl/data.frame)
##  $ manufacturer: chr [1:234] "audi" "audi" "audi" "audi" ...
##  $ model       : chr [1:234] "a4" "a4" "a4" "a4" ...
##  $ displ       : num [1:234] 1.8 1.8 2 2 2.8 2.8 3.1 1.8 1.8 2 ...
##  $ year        : int [1:234] 1999 1999 2008 2008 1999 1999 2008 1999 1999 2008 ...
##  $ cyl         : int [1:234] 4 4 4 4 6 6 6 4 4 4 ...
##  $ trans       : chr [1:234] "auto(l5)" "manual(m5)" "manual(m6)" "auto(av)" ...
##  $ drv         : chr [1:234] "f" "f" "f" "f" ...
##  $ cty         : int [1:234] 18 21 20 21 16 18 18 18 16 20 ...
##  $ hwy         : int [1:234] 29 29 31 30 26 26 27 26 25 28 ...
##  $ fl          : chr [1:234] "p" "p" "p" "p" ...
##  $ class       : chr [1:234] "compact" "compact" "compact" "compact" ...
# scatter plot
ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy)) +
  NULL

# COLOR tercera variable
ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy, color = class)) +
  NULL

# COLOR a mano (notar que color esta afuera de ases())
ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy), color = "blue") +
  NULL

# FACET
ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy)) + 
  facet_wrap(~ class, nrow = 2) +
  NULL

# Smooth
ggplot(data = mpg) + 
  geom_smooth(mapping = aes(x = displ, y = hwy)) +
  geom_point(aes(x = displ, y = hwy), color = "blue", alpha = .6) +
  NULL

# Mapping diferente en el grafico de puntos
ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) + 
  geom_point(mapping = aes(color = class), alpha = .5) + 
  geom_smooth() +
  NULL

# linetype
ggplot(data = mpg) + 
  geom_smooth(mapping = aes(x = displ, y = hwy, linetype = drv)) +
  NULL

# linetype y color
ggplot(data = mpg) + 
  geom_smooth(mapping = aes(x = displ, y = hwy, linetype = drv, color = drv)) +
  geom_point(mapping = aes(x = displ, y = hwy, color = drv)) +
  NULL

3.2 Estadísticas con ggplot2

data(diamonds)
str(diamonds)
## tibble [53,940 × 10] (S3: tbl_df/tbl/data.frame)
##  $ carat  : num [1:53940] 0.23 0.21 0.23 0.29 0.31 0.24 0.24 0.26 0.22 0.23 ...
##  $ cut    : Ord.factor w/ 5 levels "Fair"<"Good"<..: 5 4 2 4 2 3 3 3 1 3 ...
##  $ color  : Ord.factor w/ 7 levels "D"<"E"<"F"<"G"<..: 2 2 2 6 7 7 6 5 2 5 ...
##  $ clarity: Ord.factor w/ 8 levels "I1"<"SI2"<"SI1"<..: 2 3 5 4 2 6 7 3 4 5 ...
##  $ depth  : num [1:53940] 61.5 59.8 56.9 62.4 63.3 62.8 62.3 61.9 65.1 59.4 ...
##  $ table  : num [1:53940] 55 61 65 58 58 57 57 55 61 61 ...
##  $ price  : int [1:53940] 326 326 327 334 335 336 336 337 337 338 ...
##  $ x      : num [1:53940] 3.95 3.89 4.05 4.2 4.34 3.94 3.95 4.07 3.87 4 ...
##  $ y      : num [1:53940] 3.98 3.84 4.07 4.23 4.35 3.96 3.98 4.11 3.78 4.05 ...
##  $ z      : num [1:53940] 2.43 2.31 2.31 2.63 2.75 2.48 2.47 2.53 2.49 2.39 ...
ggplot(data = diamonds) + 
  geom_bar(mapping = aes(x = cut)) +
  NULL

# Cambio de estetica
ggplot(data = diamonds) + 
  stat_count(mapping = aes(x = cut), color = "steelblue2", size = 2, fill = "steelblue4") + 
  NULL

demo <- tribble(
  ~cut,         ~freq,
  "Fair",       1610,
  "Good",       4906,
  "Very Good",  12082,
  "Premium",    13791,
  "Ideal",      21551
)

# Para usar un estadistico distinto al default
ggplot(data = demo) +
  geom_bar(mapping = aes(x = cut, y = freq), stat = "identity") + 
  NULL

# Proporciones en vez de cuenta
ggplot(data = diamonds) + 
  geom_bar(mapping = aes(x = cut, y = after_stat(prop), group = 1)) + 
  NULL

# Estadisticas resumen
ggplot(data = diamonds) + 
  stat_summary(mapping = aes(x = cut, y = depth),
    fun.min = min,
    fun.max = max,
    fun = median
  )

3.3 GGPlot (position)

# Color de las barras (x igual a fill)
ggplot(data = diamonds) + 
  geom_bar(mapping = aes(x = cut, fill = cut)) + 
  NULL

## # A tibble: 8 × 6
##   clarity  Fair  Good `Very Good` Premium Ideal
##   <ord>   <int> <int>       <int>   <int> <int>
## 1 I1        210    96          84     205   146
## 2 SI2       466  1081        2100    2949  2598
## 3 SI1       408  1560        3240    3575  4282
## 4 VS2       261   978        2591    3357  5071
## 5 VS1       170   648        1775    1989  3589
## 6 VVS2       69   286        1235     870  2606
## 7 VVS1       17   186         789     616  2047
## 8 IF          9    71         268     230  1212
# Color de las barras (x distinto de fill)
ggplot(data = diamonds) + 
  geom_bar(mapping = aes(x = cut, fill = clarity)) + 
  NULL

# position = "fill" para comparar proporciones entre grupos
ggplot(data = diamonds) + 
  geom_bar(mapping = aes(x = cut, fill = clarity), position = "fill") + 
  NULL

# position = "dodge" coloca los objetos superpuestos directamente uno al lado del otro.
ggplot(data = diamonds) + 
  geom_bar(mapping = aes(x = cut, fill = clarity), position = "dodge") + 
  NULL

# position = "jitter" agrega un poco de ruido aleatorio a cada punto (evita superposicion).
ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy), position = "jitter") + 
  NULL

# Para comparar con el anterior
ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy)) +
  NULL

3.4 Time series

datos = readxl::read_excel('./data/datos_ts.xlsx', sheet='datos')

datos1 = datos %>% 
     dplyr::select(fecha, ipc) 

datos1$fecha = as.Date(datos1$fecha)

ggplot(datos1, aes(x=fecha, y=ipc)) +
  geom_line(color = 'steelblue2', linewidth = 1.2) +
  theme_minimal() +
  labs(title = 'Indice de precios al consumidor', x = 'Mes', y ='IPC') +
  theme(legend.position = 'none') +
  NULL

A veces, por problemas de escala, ggplot2 no maneja bien el eje secundario por lo que es preferible separar las series en 2 gráficos diferentes.

datos2 = datos %>% 
     dplyr::select(fecha, ipc, tcn) %>%
     rename(IPC = ipc, TCN = tcn) %>%
     pivot_longer(cols = -fecha, names_to='Var', values_to = 'Val')
datos2$fecha = as.Date(datos2$fecha)
     
g = ggplot(datos2) +
  geom_line(aes(x=fecha, y=Val, group=Var, color=Var), show.legend = TRUE) +
  theme_minimal() +
  theme(axis.text=element_text(size=12), axis.text.x = element_text(size = 10, angle = 90), legend.position="none") +
  labs(title="", x="", y="") +
  scale_x_date(date_breaks = "6 month", date_labels = "%Y-%m") +
  facet_wrap(~Var, scales = "free_y") +
  NULL
  
g

3.5 Labels

Más opciones en aquí.

# Selecciona el mejor de cada clase de acuerdo al consumo en highway

best_in_class <- mpg %>%
  group_by(class) %>%
  dplyr::filter(row_number(desc(hwy)) == 1)

ggplot(mpg, aes(displ, hwy)) +
  geom_point(aes(colour = class)) +
  geom_smooth(se = FALSE) +
  geom_label(aes(label = model), data = best_in_class, nudge_y = 2, alpha = 0.5) + 
  labs(title = "Fuel efficiency generally decreases with engine size",
       subtitle = "Two seaters (sports cars) are an exception because of their light weight",
       x = "Engine displacement (L)",
       y = "Highway fuel economy (mpg)",
       colour = "Car type",
       caption = "Data from fueleconomy.gov") + 
  NULL

3.6 Orden de factores en los ejes (variables string)

felinos = tibble(
  id = c('Leon', 'Puma', 'Gato'),
  edad = c(4, 3, 5)
)

# Default
ggplot(felinos) +
  geom_point(aes(x = id, y = edad), color = 'darkcyan', alpha = 0.7, size = 3) +
  theme(axis.text=element_text(size=14), legend.position = 'none') +
  labs(title = 'Orden alfabetico') +
  NULL

# Por orden de reinado
# Se define el orden de los factores
fel_levels <- c("Leon", "Puma", "Gato")
felinos = mutate(felinos, id=factor(id, levels = fel_levels))
ggplot(felinos) +
  geom_point(aes(x = id, y = edad), color = 'red', shape = 2, size = 3) +
  theme(axis.text=element_text(size=14), legend.position = 'none') +
  labs(title = 'Orden reinado') +
  NULL

# Por orden de edad
ggplot(felinos) +
  geom_point(aes(x=fct_reorder(id, edad), y = edad), color = 'purple', size = 3) +
  theme(axis.text=element_text(size=14), legend.position = 'none') +
  labs(title = 'Orden edad') +
  NULL

3.7 Guardar un gráfico

work = 'C:/Users/msang/'
filesave = paste0(work,'ts.png')
ggsave(filesave, g, width=10, height=8) 

Grammar of Graphics. Ver más detalles en (Wickham, Navarro, y Pedersen 2016).

Nota: la mayor parte de esta sección se basa en el Capitulo 3 del libro R for Data Science. Al final hay un ejemplo interesante de como trabajar con strings.

Mas detalles en el Capitulo 28.

Otra referencia para ver código es: The R Graph Gallery

Bibliografia

Wickham, Hadley, Danielle Navarro, y Thomas Lin Pedersen. 2016. ggplot2: Elegant Graphics for Data Analysis. Springer. https://ggplot2-book.org/.