Volver al inicio

Unidad 5. Otros tipos y parámetros gráficos

Gráficos de área

Para trabajar en de aquí en adelante utilizaremos otra base de datos. La misma la armé en base a los datos de superficie cultivada, producción y rendimiento de soja en Argentina y el mundo (extraída de informes de la FAO1) desde 1960 hasta 2023.

soja <- read_csv("produccion_soja_2023.csv")

# Dividiremos la base de datos en dos
mundo <- soja %>%
  filter(Area == "World")

argentina <- soja %>%
  filter(Area == "Argentina")

En primer lugar introduciremos un nuevo geom: geom_area. Como su nombre lo indica, permite graficar superficies completas en base a una escala continua. En este caso usaremos como eje x los años, como si fueran continuos. Así por ejemplo podemos graficar la variación de la superficie cultivada a lo largo del tiempo:

ggplot(argentina, aes(Year, Sup/1000000))+ # editamos la sup para no ver números tan grandes
  geom_area(fill="cornflowerblue", col="gray21") +
  scale_y_continuous(expand = c(0,0), breaks = seq(0, 25, by = 5))+
  scale_x_continuous(expand = c(0,0),breaks = seq(1960,2025, by=5))+
  labs(x= "Años",
    y= "Superficie sembrada [millones de ha]") +
  THEME

Ahora supongamos que queremos graficar al mismo tiempo la superficie de Argentina y la global. Una opción sería dividir la variable Sup entre las regiones por fill.

ggplot(soja, aes(Year, Sup/1000000, fill=Area))+
  geom_area(col="gray21") +
  scale_y_continuous(expand = c(0,0), breaks = seq(0, 150, by = 10))+
  scale_x_continuous(expand = c(0,0),breaks = seq(1960,2025, by=5))+
  labs(x= "Años",
    y= "Superficie sembrada [millones de ha]") +
  THEME

Si bien parece funcionar, al incluir esta opción geom_area apila los datos de una región con la otra. Por lo tanto, lo que vamos a hacer es superponer dos gráficos de área al mismo tiempo. Para ello introduciremos una nueva idea que es la de utilizar dos bases de datos diferentes en el mismo gráfico. Cuando creamos nuestro gráfico (ggplot(aes(…))) los geom que introduzcamos luego “heredan” tanto la base de datos como la estructura x-y determinada por aes que acompaña a ggplot. Si nuestro nuevo geom requiere una diferente, debemos expresamente introducirla. Finalmente, como la inclusión de nuevos geom no incorpora una leyenda, con la función annotate podemos introducir texto en algún lugar específico para clarificar qué significa cada área. También es posible introducir segmentos, flechas y otros elementos con esta función. Veamos cómo quedaría:

ggplot(mundo, aes(Year, Sup/1000000))+ # aes principal
  geom_area(fill="burlywood3", col="gray21") + # primer área, es la que va al fondo
  scale_y_continuous(expand = c(0,0), breaks = seq(0,120, by = 10))+
  scale_x_continuous(expand = c(0,0),breaks = seq(1960,2025, by=5))+
  labs(x= "Años",
       y= "Superficie sembrada [millones de ha]") +
  geom_area(data= argentina, aes(Year, Sup/1000000), # segunda, aparece al frente
            fill="cornflowerblue", col="gray21")+
  annotate("text", x=2008, y= 8, label = "Argentina", # agregamos texto en un lugar específico
           size=6)+
  annotate("text", x=1990, y= 35, label = "Mundo", size=6) +
  THEME

Entonces ahora nos queda un idea mucho mejor de cómo a crecido la superficie sembrada de Argentina respecto a la del resto del mundo.

Aquí hemos expuesto otra de las funcionalidades que nos facilita ggplot2: introducir más de un geom a la vez. Este puede ser del mismo tipo o diferente, como veremos a continuación.

Combinando gráficos de distinto tipo

También puede resultarnos de utilidad combinar gráficos de dos tipos diferentes. Esta opción es muy útil y sencilla de utilizar, sin embargo hay un par de condiciones a cumplir:

  • el eje x debe ser el mismo.
  • el eje y también debe ser el mismo, o al menos ser “compatible” en escala (podría introducirse un eje secundario, pero excede al contenido de este taller).

Una vez cumplidas estas condiciones, es solo cuestión de usar nuestra creatividad para crear el mejor gráfico. Supongamos como ejemplo que queremos comparar el rendimiento de la soja en Argentina contra el promedio mundial. Podemos hacer un gráfico de columnas clasificando por región:

soja %>% mutate(Area=fct_recode(Area,
                              "Argentina"="Argentine", # modificamos los factores al español
                              "Mundo" ="World")) %>%
ggplot(aes(Year, Yield/1000, fill=Area))+
  geom_col(position="dodge") +
  scale_y_continuous(expand = c(0,0), breaks = seq(0,5, by = .5))+
  scale_x_continuous(expand = c(0,0),breaks = seq(1960,2025, by=5))+
  labs(x= "Años",
       y= "Rendimiento [Tn/ha]")+
  THEME +
  theme(legend.position = c(.2,.85))

Como vemos, de esta manera nos quedan demasiadas columnas y es muy difícil tener una idea clara del patrón. En cambio vamos a colocar el rendimiento global como puntos unidos por una línea. Para ello utilizaremos las bases de datos argentina y mundo. Además vemos que las comas del eje Y aparecen como puntos, lo modificaremos al formato del español:

ggplot(argentina, aes(Year, Yield/1000))+ # base de datos de argentina
  geom_col(fill="cornflowerblue") +  # creamos las columnas
  scale_y_continuous(expand = c(0,0), breaks = seq(0,5, by = .5),
                     labels=function(x) format(x, decimal.mark = ",", # cambio . por ,
                                               scientific = FALSE))+
  scale_x_continuous(expand = c(0,0),breaks = seq(1960,2025, by=5))+
  labs(x= "Años",
       y= "Rendimiento [Tn/ha]")+
  geom_line(data= mundo, aes(Year, Yield/1000), # segundo geom, del mundo
            col="red")+
  geom_point(data= mundo, aes(Year, Yield/1000), # tercer geom, de nuevo hay que especificar
            col="red", size=2)+
  annotate("text", x=1990, y= 2.5, label = "Argentina", col="cornflowerblue", size=5)+
  annotate("text", x=1965, y= 1.6, label = "Mundo", col="red", size=5) +
  THEME

Ahora nos resulta mucho más fácil diferenciar en qué años (o períodos) el rendimiento fue mayor en Argentina que el promedio global.

Eje secundario

Si bien el uso de gráficos con ejes secundarios no fue planteado por el creador de ggplot2 por no considerarlo útil (idea que comparto), se puede incorporar mediante el parámetro sec.axis dentro de scale_y_continuos . Es importante destacar que este eje secundario se debe plantear como una transformación del eje primario. Esto limita fuertemente su uso, y en este curso simplemente aproximaremos una forma de hacerlo para ilustrar la segunda variable de una forma “aproximada”.

Supongamos que queremos graficar, siguiendo con nuestra base de datos, el rendimiento y la producción de soja en Argentina a lo largo del tiempo, en el mismo gráfico. Tomaremos como eje primario el de rendimiento, y secundario el de producción. Como un eje tiene que se una proporción del otro, creamos una nueva variable que nos indique la relación entre ellos:

argentina <- argentina %>% 
  mutate(Relacion = Production/(Yield/1000))

Y luego utilizaremos el valor máximo de estar relación para graficar y que ambas variables se “observen” en una escala similar. Luego deberemos realizar una conversión de la escala a poner en el eje secundario siguiendo un patrón similar. Como vamos a usar la relación máxima entre rendimiento y producción, el valor graficado será aproximado ya que cada año dicha relación será diferente. Sin embargo, veremos que la aproximación es bastante buena y sirve de forma representativa.

ggplot(argentina, aes(x=Year))+ # especificamos el eje x
  geom_col(aes(y=Yield/1000),  # luego en cada geom el eje y
           fill="darkolivegreen2") +
  scale_y_continuous(expand = c(0,0), limits=c(0,3.5),
                     breaks = seq(0,5, by = .5), 
                     sec.axis =
                       sec_axis(~.*max(argentina$Relacion)/1000000, #la relación de los ejes  
                        name="Producción [millones de Tn]", # título
                        breaks=seq(0,65, by=5)))+
  scale_x_continuous(expand = c(0,0),breaks = seq(1960,2023, by=5))+
  labs(x= "Años",
       y= "Rendimiento [Tn/ha]")+
  geom_line(aes(y=Production/max(Relacion)), 
            col="blue3")+ 
  geom_point(aes(y=Production/max(Relacion)), 
            col="blue3", size = 4)+
  annotate("text", x=1990, y= 2.5, label = "Rendimiento", col="darkolivegreen4", size=6)+
  annotate("text", x=2010, y= 1, label = "Producción", col="blue3", size=6) +
  THEME

Pivoteando (pivoting)

La última funcionalidad que veremos en este taller es el uso de pivot_longer y pivot_wider. Estas dos funciones tienen usos opuestos y veremos de a una cómo se usan, ya que nos permite transformar completamente la estructura de la base de datos, a partir de intercambiar columnas por filas (o viceversa).

pivot_longer

Nos permite agrupar diferentes variables (que tengamos en varias columnas) en una que contenga el nombre de la categoría (que antes era el nombre de una columna) y otra que contenga el valor numérico que corresponde a cada una. Nada mejor para ilustrarlo que un ejemplo. Recordemos nuestra base de datos soja que tenía esta estructura inicial:

head(soja)
# A tibble: 6 × 6
  Area      Element         Year   Sup Production Yield
  <chr>     <chr>          <dbl> <dbl>      <dbl> <dbl>
1 Argentina Area harvested  1961   980        957   977
2 Argentina Area harvested  1962  9649      11220  1163
3 Argentina Area harvested  1963 19302      18920   980
4 Argentina Area harvested  1964 12220      14000  1146
5 Argentina Area harvested  1965 16422      17000  1035
6 Argentina Area harvested  1966 15689      18200  1160

Supongamos ahora que queremos crear una columna que contenga en sus filas el tipo de parámetro que estamos midiendo (superficie, producción o rendimiento) y otra que contenga el valor del parámetro correspondiente. La estructura básica de pivot_longer es la siguiente:

pivot_longer(c(`variable_1`, `variable_2`, ... , `variable_n`), # variables a combinar
       names_to = "Variables", # el titulo de la nueva columna con las variables
       values_to = "Valor") # el título de la nueva columna con el valor numérico

Notar que el nombre de las variables se debe introducir entre tildes invertidas (`). En nuestro caso de ejemplo será:

soja %>% pivot_longer(c(`Sup`, `Yield`, `Production`),
       names_to =  "Variables",
       values_to = "Valor")
# A tibble: 378 × 5
   Area      Element         Year Variables  Valor
   <chr>     <chr>          <dbl> <chr>      <dbl>
 1 Argentina Area harvested  1961 Sup          980
 2 Argentina Area harvested  1961 Yield        977
 3 Argentina Area harvested  1961 Production   957
 4 Argentina Area harvested  1962 Sup         9649
 5 Argentina Area harvested  1962 Yield       1163
 6 Argentina Area harvested  1962 Production 11220
 7 Argentina Area harvested  1963 Sup        19302
 8 Argentina Area harvested  1963 Yield        980
 9 Argentina Area harvested  1963 Production 18920
10 Argentina Area harvested  1964 Sup        12220
# ℹ 368 more rows

pivot_wider

La función pivot_wider hace exactamente lo contrario que pivot_longer, nos permite a partir de una columna con varios niveles de un factor, crear múltiples columnas (una para cada nivel del factor). Para utilizarla, cada fila que tengamos tiene que ser única (es decir, lo elementos que no son variables respuestas no pueden ser los mismos entre dos filas) para que no se genere confusión. La estructura general es la siguiente:

pivot_wider(names_from = variable, # variable a dividir
       values_from = Valor) # variable respuesta numérica a repartir

Entonces, a modo de ejemplo, supongamos que queremos comparar como se ha incrementado la producción de soja en Argentina y el mundo desde 1961 hasta 2023. Para ello podemos primero seleccionar las variables de interés (solo nos interesa la producción), después filtrar los años de interés y crear nuevas columnas.

soja %>% select(Area, Year, Production) %>% # seleccionamos
  filter(Year==1961 | Year==2023) %>%  # filtramos
  pivot_wider(names_from =  Year, values_from = Production) %>% # repartimos en columnas
  mutate(Prop= round(`2023`/`1961`, 0)) # transformamos con las variables entre ` `
# A tibble: 2 × 4
  Area        `1961`    `2023`  Prop
  <chr>        <dbl>     <dbl> <dbl>
1 Argentina      957  25044978 26170
2 World     26883158 371173609    14

Podemos ver como en Argentina en el último medio siglo se incrementó la producción 26170 veces, mientras que a nivel global 1381 veces.

Estas funciones tienen diferentes usos. Como vimos, pivot_wider puede servirnos para convertir variables y comparar niveles de un factor. pivot_longer puede servir tanto para corregir bases mal armadas como para generar nuevos criterios de clasificación que pueden ser útiles en algunos gráficos.

Por ejemplo final, supongamos que queremos ver en un mismo gráfico qué porcentaje de la producción global y de la superficie global sembrada representa Argentina. Para ello vamos a:

  • seleccionar las columnas de interés
  • unir producción y superficie en una única columna (pivot_longer)
  • dividir Argentina y Mundo en dos columnas (pivot_wider)
  • calcular la proporción que representa Argentina del global y con ella el porcentaje
  • graficar aplicando como criterio de clasificación del color la columna que especifica si se trata de producción o superficie.

Quedaría de la siguiente manera:

soja %>%
  select(Area, Year, Sup, Production)%>%
  pivot_longer(c(`Sup`, `Production`), names_to = "variable", values_to = "value") %>%
  pivot_wider(names_from = Area, values_from = value) %>%
  mutate(
    prop = Argentina/World,
    porc = prop*100  # notar que podemos usar la variable recién creada
  )%>%
  ggplot(aes(Year, porc, col=variable))+
  geom_point()+
  geom_line()+
  scale_y_continuous(limits=c(0,30),expand = c(0,0), breaks = seq(0, 25, by = 2))+
  scale_x_continuous(expand = c(0,0),breaks = seq(1960,2025, by=5))+
  labs(x= "Años",
       y= "Porcentaje del global")+
  scale_colour_manual(values=c("Sup"= "blue4","Production"="red"), guide= "none")+
  annotate("text", x=2007, y=10, label="Superficie\ncultivada", col="blue4", size=5)+
  annotate("text", x=1995, y=18, label="Producción", col="red", size=5) +
  THEME

Gráficos de biplot para análisis multivariado

Esta sección tiene por objetivo mostrar que el conocimiento de los gráficos con ggplot2 sobrepasan al uso individual de este paquete, sino que hay mucho otros que se basan en él para generar gráficos. Un ejemplo de ello es el paquete factoextra para gráficos multivariados.

Vamos a desarrollar un ejemplo donde armamos un biplot a partir de un análisis de componentes principales (PCA). Vamos a retomar a la base de datos ALIM, y haremos un PCA comparando la concentración de distintos metales en los órganos, su peso seco y verdor. Para ello ejecutamos:

library(factoextra);library(FactoMineR);library(ggrepel)
Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa

Attaching package: 'factoextra'
The following object is masked from 'package:agricolae':

    hcut
res.pca <- PCA(ALIM[, -c(1:5)], scale.unit = TRUE)

Una vez creado el objeto de resultado de nuestro PCA, vamos a realizar un gráfico de biplot con la función fviz_pca_biplot de factoextra:

BIPLOT <- fviz_pca_biplot(res.pca, 
                repel = TRUE,
                geom.ind = "point",
                col.var = "deeppink4", 
                col.ind = "black",
                labelsize=5,
                axes.linetype = "blank",
                alpha.var=0.5,
                title = NULL) ; BIPLOT

Ahora vamos a realizar algunas modificaciones estéticas, y a incluir una clasificación por color según el órgano de el que se trate. Para ello vamos a crear un objeto nuevo con los porcentajes de explicación de cada eje:

VARIANCE <- round(get_eigenvalue(res.pca)[,2], 2)


BIPLOT +
  geom_point(aes(col = ALIM$Organo),size = 4)+
  geom_hline(yintercept = 0, linetype = "dotted", col = "grey30")+
  geom_vline(xintercept = 0, linetype = "dotted", col = "grey30")+
  labs(x = paste("PC 1 (", VARIANCE[[1]], "%)"),
       y = paste("PC 2 (", VARIANCE[[2]], "%)"),
       col = "Órgano") +
  scale_y_continuous(expand = c(0,0), limits = c(-3,3), 
                     breaks = seq(-40,40, by = 1))+
  scale_x_continuous(expand = c(0,0), limits = c(-5.5,5.5), 
                     breaks = seq(-9,9, by = 2)) +
  scale_colour_viridis_d() +
  THEME

Volver al inicio

Footnotes

  1. FAOSTATS. https://www.fao.org/faostat/en/#data/QCL↩︎