Graficación con R - histogramas, gráficos de densidad, dispersión y otros

Preparativos

Carga de paquetes

# Carga de dplyr
library(dplyr)

# Carga de ggplot2
library(ggplot2)

# Carga de hrbrthemes (temas adicionales para ggplot2)
library(hrbrthemes)

Conjuntos de datos utilizados

Promedios de LST, NDVI y NDBI de los cantones de la GAM
Este conjunto de datos forma parte del Atlas de Servicios Ecosistémicos de la Gran Área Metropolitana (GAM). Para cada uno de los 31 cantones de la GAM se incluyen los promedios de:

# Carga de datos desde un archivo CSV
lst_ndvi_ndbi <-
  read.csv(file = 'https://raw.githubusercontent.com/gf0604-procesamientodatosgeograficos/2021i-datos/main/atlasverde/lst-ndvi-ndbi/lst_ndvi_ndbi-cantones_gam.csv')

Análisis de datos de LST, NDVI y NDBI de la GAM

Despliegue de los datos tabulares

# Estructura del conjunto de datos
str(lst_ndvi_ndbi)
'data.frame':   31 obs. of  4 variables:
 $ canton       : chr  "Alajuela" "Alajuelita" "Alvarado" "Aserrí" ...
 $ lst_promedio : num  42.1 38.1 33.5 35.8 41.4 ...
 $ ndvi_promedio: num  0.526 0.548 0.6 0.623 0.591 ...
 $ ndbi_promedio: num  -0.197 -0.222 -0.256 -0.261 -0.224 ...
# Primeros registros
slice_head(lst_ndvi_ndbi, n = 5)
      canton lst_promedio ndvi_promedio ndbi_promedio
1   Alajuela     42.11327     0.5258936    -0.1971417
2 Alajuelita     38.06614     0.5478143    -0.2222383
3   Alvarado     33.47862     0.6002681    -0.2558038
4    Aserrí     35.79543     0.6230744    -0.2607592
5     Atenas     41.35840     0.5913761    -0.2237017
# Últimos registros
slice_tail(lst_ndvi_ndbi, n = 5)
                canton lst_promedio ndvi_promedio ndbi_promedio
1            Santa Ana     39.28124     0.5408581   -0.22599949
2        Santa Barbara     36.30114     0.6548259   -0.30456919
3        Santo Domingo     41.00884     0.4996296   -0.19275645
4               Tibás     43.98472     0.2372620   -0.05957896
5 Vázquez de Coronado     30.34446     0.5450616   -0.25486747

Histogramas

Un histograma es una representación gráfica de la distribución de una variable numérica en forma de barras (bins). La altura de cada barra representa la frecuencia de un rango de valores de la variable.

# Histograma de LST
ggplot(lst_ndvi_ndbi, aes(x = lst_promedio)) +
  geom_histogram(binwidth = 2,
                 color = "red",
                 fill = "white") +
  ggtitle("Distribución de LST en la GAM") +
  xlab("LST") +
  ylab("Frecuencia") +
  theme_ipsum()
# Histograma de NDVI
ggplot(lst_ndvi_ndbi) +
  geom_histogram(
    aes(x = ndvi_promedio),
    binwidth = 0.1,
    color = "green",
    fill = "white"
  ) +
  ggtitle("Distribución de NDVI en la GAM") +
  xlab("NDVI") +
  ylab("Frecuencia") +
  theme_ipsum()
# Histograma de NDBI
ggplot(lst_ndvi_ndbi) +
  geom_histogram(
    aes(x = ndbi_promedio),
    binwidth = 0.05,
    color = "black",
    fill = "white"
  ) +
  ggtitle("Distribución de NDBI en la GAM") +
  xlab("NDBI") +
  ylab("Frecuencia") +
  theme_ipsum()

Ejercicio: grafique las variables de NDVI y NDBI en un mismo histograma.

Gráficos de densidad

Un gráfico de densidad representa mediante una curva la distribución de una variable numérica. Utiliza una estimación de densidad de kernel para mostrar la función de densidad de probabilidad de una variable.

# Gráfico de densidad de NDVI
ggplot(lst_ndvi_ndbi) +
  geom_density(
    aes(x = ndvi_promedio),
    color = "black",
    fill = "green",
    alpha = 0.4
  ) +
  ggtitle("Distribución de NDVI en la GAM") +
  xlab("NDVI") +
  ylab("Densidad") +
  theme_ipsum()

Ejercicio: agregue un histograma al gráfico de densidad de NDVI.

Gráficos de lollipops

Un gráfico de lollipop es similar a un gráfico de barras, en el cual las barras se transforman en líneas que finalizan en un círculo. Muestran la relación entre una variable categórica y una variable numérica.

# Gráfico de lollipop que muestra el promedio de NDVI en cada cantón de la GAM
lst_ndvi_ndbi %>%
  arrange(ndvi_promedio) %>%
  mutate(canton = factor(canton, canton)) %>%
  ggplot(aes(x = canton, y = ndvi_promedio)) +
  geom_segment(aes(
    x = canton,
    xend = canton,
    y = 0,
    yend = ndvi_promedio
  ), color = "grey") +
  geom_point(size = 3, color = "#69b3a2") +
  coord_flip() +
  theme_ipsum() +
  ggtitle("Promedio de NDVI en cantones de la GAM") +
  xlab("Cantón") +
  ylab("NDVI") +  
  theme(
    text = element_text(size = 8),
    panel.grid.minor.y = element_blank(),
    panel.grid.major.y = element_blank(),
    legend.position = "none"
  )

Ejercicio: genere un gráfico de lollipop que muestre el LST promedio en cada cantón.
Ejercicio: genere un gráfico de lollipop que muestre conjuntamente el NDVI promedio y el NDBI promedio en cada cantón.

Gráficos de dispersión

Un gráfico de dispersión (scatterplot) muestra la relación entre dos variables numéricas. Para cada punto de datos, el valor de una variable es representado en el eje x y el valor de la otra variable en el eje y.

# Gráfico de dispersión de NDVI y LST
ggplot(lst_ndvi_ndbi, aes(x = ndvi_promedio)) +
  geom_point(
    aes(y = lst_promedio)
  ) +
  ggtitle("Relación entre NDVI y LST en la GAM") +
  xlab("NDVI") +
  ylab("LST") +
  theme_ipsum()

Otros

Gráfico de doble eje

library(plotly)

# Ordenar de mayor a menor LST
df_lst_ndbi_ndvi.temp <-
  order(lst_ndvi_ndbi$lst_promedio, decreasing = FALSE)
# Nuevo data frame ordenado
df_lst_ndbi_ndvi.ordenado_lst <-
  lst_ndvi_ndbi[df_lst_ndbi_ndvi.temp, ]

ay <- list(
  tickfont = list(color = "green"),
  overlaying = "y",
  side = "right",
  title = "NDVI"
)

plot_ly(
  data = df_lst_ndbi_ndvi.ordenado_lst,
  x = ~ reorder(canton,-lst_promedio),
  y = ~ lst_promedio,
  name = 'LST',
  type = 'scatter',
  mode = 'lines',
  line = list(color = "red")
) %>%
  add_trace(
    y = ~ ndvi_promedio,
    name = 'NDVI',
    mode = 'lines',
    line = list(color = "green"),
    yaxis = "y2"
  ) %>%
  layout(
    title = "La vegetación urbana regula la temperatura",
    yaxis = list(title = "LST", tickfont = list(color = "red")),
    yaxis2 = ay,
    xaxis = list(title = "Cantón"),
    legend = list(x = 0.5, y = 1.0),
    hovermode = "compare"
  )  %>%
  config(locale = "es")

Mapa

#-------------------- Paquetes --------------------

library(flexdashboard)
library(dplyr)
library(sf)
library(leaflet)
library(leaflet.extras)
library(leaflet.opacity)
library(leafem)
library(esri2sf)
library(raster)

#--------------- URL de geoservicios --------------

url_agfs_limite_gam <-
  "https://services9.arcgis.com/RrvMEynxDB8hycVO/arcgis/rest/services/gam_limite_gam/FeatureServer/0"

url_raster_lst <-
  "https://raw.githubusercontent.com/atlas-servicios-ecosistemicos-gam/datos-calentamiento-urbano/master/gam/LST_GAM_WEB.TIF"

#--------------- Objetos sf y raster ---------------

# Límite de la GAM
sf_limite_gam <-
  esri2sf(url_agfs_limite_gam)
[1] "Feature Layer"
[1] "esriGeometryPolygon"
[1] "Coordinate Reference System: 3857"
# Límite de la GAM (reproyectado a Web Mercator)
sf_limite_gam_web <- 
  sf_limite_gam %>%
  st_transform(3857)

# Capa raster de LST (en Web Mercator)
raster_lst <-
  raster(url_raster_lst) %>%
  crop(sf_limite_gam_web) %>%
  mask(sf_limite_gam_web)

#---------------- Paletas de colores ---------------

# LST
colores_lst <- c("blue", "green", "yellow", "red")
pal_lst <- 
  colorNumeric(
    colores_lst, 
    values(raster_lst),
    na.color = "transparent"
  )

# Mapa
leaflet() %>%
  addProviderTiles(providers$OpenStreetMap.Mapnik, group = "OpenStreetMap") %>%
  addProviderTiles(providers$CartoDB.DarkMatter, group = "CartoDB Dark Matter") %>%
  addProviderTiles(providers$Stamen.TonerLite, group = "Stamen Toner Lite") %>%
  addProviderTiles(providers$Esri.WorldImagery, group = "Imágenes de ESRI") %>%
  addPolygons(
    data = sf_limite_gam,
    color = "Purple",
    fillColor = "transparent",
    stroke = TRUE,
    weight = 6.0,
    group = "Límite de la GAM"
  ) %>%
  addRasterImage(
    raster_lst, 
    layerId = "raster",    
    colors = pal_lst,
    opacity = 0.6,
    group = "LST"
  ) %>%  
  addLegend(
    title = "LST (°C)",
    values = values(raster_lst),
    pal = pal_lst,
    position = "bottomright",
    group = "LST"
  ) %>%    
  addLayersControl(
    baseGroups = c("OpenStreetMap", "CartoDB Dark Matter", "Stamen Toner Lite", "Imágenes de ESRI"),
    overlayGroups = c("Límite de la GAM", "LST"),
    options = layersControlOptions(collapsed = TRUE)    
  ) %>%  
  addMiniMap(
    toggleDisplay = TRUE,
    position = "bottomleft",
    tiles = providers$OpenStreetMap.Mapnik
  ) %>%
  addScaleBar(
    position = "bottomleft",
    options = scaleBarOptions(imperial = FALSE)
  ) %>%
  addMouseCoordinates() %>%
  addSearchOSM() %>%
  addResetMapButton() %>%
  addOpacitySlider(layerId = "raster")

Corrections

If you see mistakes or want to suggest changes, please create an issue on the source repository.

Reuse

Text and figures are licensed under Creative Commons Attribution CC BY-SA 4.0. Source code is available at https://github.com/gf0604-procesamientodatosgeograficos/2021i-leccion-10/, unless otherwise noted. The figures that have been reused from other sources don't fall under this license and can be recognized by a note in their caption: "Figure from ...".