library(plotly)
## Loading required package: ggplot2
## 
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
library(ggplot2)
library(maps)
library(ggmap)
## The legacy packages maptools, rgdal, and rgeos, underpinning the sp package,
## which was just loaded, will retire in October 2023.
## Please refer to R-spatial evolution reports for details, especially
## https://r-spatial.org/r/2023/05/15/evolution4.html.
## It may be desirable to make the sf package available;
## package maintainers should consider adding sf to Suggests:.
## The sp package is now running under evolution status 2
##      (status 2 uses the sf package in place of rgdal)
## ℹ Google's Terms of Service: <https://mapsplatform.google.com>
## ℹ Please cite ggmap if you use it! Use `citation("ggmap")` for details.
## 
## Attaching package: 'ggmap'
## 
## 
## The following object is masked from 'package:plotly':
## 
##     wind
library(sp)
library(stats)
library(graphics)
library(rnaturalearth)
## Support for Spatial objects (`sp`) will be deprecated in {rnaturalearth} and will be removed in a future release of the package. Please use `sf` objects with {rnaturalearth}. For example: `ne_download(returnclass = 'sf')`
library(plotly)
Sys.setenv('MAPBOX_TOKEN' = 'pk.eyJ1IjoibWFra2thcmVuYSIsImEiOiJjbG1wZnYwamoxYXNwMmxuMTlqNzJ6bTR5In0.yuZ21vnkPlHPCIypn50BDw')
  1. Mapas Hay muchas formas de dibujar mapas, cada una con sus propias fortalezas y debilidades. Los métodos generalmente se dividen en dos categorías: integración o individualización. Los mapas integrados utilizan la compatibilidad integrada con plotly.js para mostrar las capas del mapa base. Actualmente, existen dos métodos admitidos para crear mapas incrustados: usar Mapbox y usar mapas base incrustados proporcionados por d3.js. Un enfoque integrado es útil cuando desea un mapa rápido y no necesita necesariamente una representación elegante de las características geoespaciales.

4.1 Mapas integrados 4.4.1 Resumen Si tiene datos de latitud/longitud bastante simples y desea crear un mapa rápidamente, puede probar una de las opciones de mapeo integradas de plotlyplot_mapbox() (es decir, y plot_geo() ).

plot_mapbox(maps::canada.cities) %>%
  add_markers(
    x = ~long, 
    y = ~lat, 
    size = ~pop, 
    color = ~country.etc,
    colors = "Accent",
    text = ~paste(name, pop),
    hoverinfo = "text"
  )
## Warning: `line.width` does not currently support multiple values.

## Warning: `line.width` does not currently support multiple values.

## Warning: `line.width` does not currently support multiple values.

## Warning: `line.width` does not currently support multiple values.

## Warning: `line.width` does not currently support multiple values.

## Warning: `line.width` does not currently support multiple values.

## Warning: `line.width` does not currently support multiple values.

## Warning: `line.width` does not currently support multiple values.

## Warning: `line.width` does not currently support multiple values.

## Warning: `line.width` does not currently support multiple values.

## Warning: `line.width` does not currently support multiple values.

## Warning: `line.width` does not currently support multiple values.

## Warning: `line.width` does not currently support multiple values.
## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Accent is 8
## Returning the palette you asked for with that many colors

FIGURA 4.1: La grafica 4.1 es un gráfico de burbujas potenciado por mapbox que muestra la población de varias ciudades en Canadá.

library(listviewer)
styles <- schema()$layout$layoutAttributes$mapbox$style$values
styles
##  [1] "basic"             "streets"           "outdoors"         
##  [4] "light"             "dark"              "satellite"        
##  [7] "satellite-streets" "carto-darkmatter"  "carto-positron"   
## [10] "open-street-map"   "stamen-terrain"    "stamen-toner"     
## [13] "stamen-watercolor" "white-bg"
#>  [1] "basic"             "streets"          
#>  [3] "outdoors"          "light"            
#>  [5] "dark"              "satellite"        
#>  [7] "satellite-streets" "open-street-map"  
#>  [9] "white-bg"          "carto-positron"   
#> [11] "carto-darkmatter"  "stamen-terrain"   
#> [13] "stamen-toner"      "stamen-watercolor"
layout(
  plot_mapbox(), 
  mapbox = list(style = "satellite")
)
## No scattermapbox mode specifed:
##   Setting the mode to markers
##   Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode

FIGURA 4.2: La figura 4.2 muestra el mapa base de imágenes satelitales de la tierra.

style_buttons <- lapply(styles, function(s) {
  list(
    label = s, 
    method = "relayout", 
    args = list("mapbox.style", s)
  )
})
layout(
  plot_mapbox(), 
  mapbox = list(style = "dark"),
  updatemenus = list(
    list(y = 0.8, buttons = style_buttons)
  )
)
## No scattermapbox mode specifed:
##   Setting the mode to markers
##   Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode

FIGURA 4.3: La Figura 4.3 muestra cómo crear una lista desplegable incorporada de plotly.js para controlar el estilo del mapa base a través de layout.updatemenus. Además, proporciona una lista de botones (es decir, elementos de menú) donde cada botón llama al método plotly.js con algunos argumentos.

library(plotly)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
# airport locations
air <- read.csv(
  'https://plotly-r.com/data-raw/airport_locations.csv'
)
# flights between airports
flights <- read.csv(
  'https://plotly-r.com/data-raw/flight_paths.csv'
)
flights$id <- seq_len(nrow(flights))

# map projection
geo <- list(
  projection = list(
    type = 'orthographic',
    rotation = list(lon = -100, lat = 40, roll = 0)
  ),
  showland = TRUE,
  landcolor = toRGB("gray95"),
  countrycolor = toRGB("gray80")
)

plot_geo(color = I("red")) %>%
  add_markers(
    data = air, x = ~long, y = ~lat, text = ~airport,
    size = ~cnt, hoverinfo = "text", alpha = 0.5
  ) %>%
  add_segments(
    data = group_by(flights, id),
    x = ~start_lon, xend = ~end_lon,
    y = ~start_lat, yend = ~end_lat,
    alpha = 0.3, size = I(1), hoverinfo = "none"
  ) %>%
  layout(geo = geo, showlegend = FALSE)
## Warning: `line.width` does not currently support multiple values.

FIGURA 4.4: La Figura 4.4 muestra el uso de plot_geo() en combinación con add_markers() y add_segments() para mostrar las rutas de vuelo de los Estados Unidos. plot_mapbox() está fijo en la proyección de Mercator, pero hay varias proyecciones diferentes disponibles para el constructor plot_geo(), incluida una proyección ortográfica que da la ilusión de una Tierra en 3D.

map1 <- plot_mapbox() %>% 
  add_segments(x = -100, xend = -50, y = 50, yend = 75) %>%
  layout(
    mapbox = list(
      zoom = 0,
      center = list(lat = 65, lon = -75)
    )
  )

map2 <- plot_geo() %>% 
  add_segments(x = -100, xend = -50, y = 50, yend = 75) %>%
  layout(geo = list(projection = list(type = "mercator")))

library(htmltools)
browsable(tagList(map1, map2))

plot_geo() proyecta automáticamente la geometría en el sistema de coordenadas apropiado definido por la proyección del mapa. Figura 4.5, Línea única usando plot_mapbox(), curva usando plot_geo()

4.1.2 Coropletas

density <- state.x77[, "Population"] / state.x77[, "Area"]

g <- list(
  scope = 'usa',
  projection = list(type = 'albers usa'),
  lakecolor = toRGB('white')
)

plot_geo() %>%
  add_trace(
    z = ~density, text = state.name, span = I(0),
    locations = state.abb, locationmode = 'USA-states'
  ) %>%
  layout(geo = g)

La Figura 4.6 muestra la densidad de población de los EE. UU. a través del rastro de coropletas utilizando los datos estatales de los EE. UU. del paquete de conjuntos de datos (R Core Team 2016 ) . Simplemente proporcionando un zatributo, plotly_geo()

plot_ly() %>%
  add_trace(
    type = "choroplethmapbox",
    # See how this GeoJSON URL was generated at
    # https://plotly-r.com/data-raw/us-states.R
    geojson = paste(c(
      "https://gist.githubusercontent.com/cpsievert/",
      "7cdcb444fb2670bd2767d349379ae886/raw/",
      "cf5631bfd2e385891bb0a9788a179d7f023bf6c8/", 
      "us-states.json"
    ), collapse = ""),
    locations = row.names(state.x77),
    z = state.x77[, "Population"] / state.x77[, "Area"],
    span = I(0)
  ) %>%
  layout(
    mapbox = list(
      style = "light",
      zoom = 4,
      center = list(lon = -98.58, lat = 39.82)
    )
  ) %>%
  config(
    mapboxAccessToken = Sys.getenv("MAPBOX_TOKEN"),
    # Workaround to make sure image download uses full container
    # size https://github.com/plotly/plotly.js/pull/3746
    toImageButtonOptions = list(
      format = "svg", 
      width = NULL, 
      height = NULL
    )
  )

La Figura 4.7 demuestra cómo podríamos visualizar la misma información que la Figura 4.6 , pero esta vez usando choroplethmapbox.

4.2 Mapas personalizados 4.2.1 Características simples (sf)

library(rnaturalearth)
world <- ne_countries(returnclass = "sf")
class(world)
## [1] "sf"         "data.frame"
#> [1] "sf"    "data.frame"
plot_ly(world, color = I("gray90"), stroke = I("black"), span = I(1))
## No trace type specified:
##   Based on info supplied, a 'scatter' trace seems appropriate.
##   Read more about this trace type -> https://plotly.com/r/reference/#scatter

FIGURA 4.8: El paquete rnaturalearth es el mejor paquete para obtener todos los datos del mapa del mundo a través de la API. Figura 4.8: Trace todos los países del mundo usando las funciones plot_ly() y ne_countries() del paquete rnaturalearth.

Los siguientes códigos, usan la impresión para sf en marcos de datos para demostrar que toda la información necesaria para representar los países (es decir, polígonos).

library(sf)
## Linking to GEOS 3.11.2, GDAL 3.6.2, PROJ 9.2.0; sf_use_s2() is TRUE
world %>%
  select(name) %>%
  print(n = 4)
## Simple feature collection with 177 features and 1 field
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: -180 ymin: -90 xmax: 180 ymax: 83.64513
## Geodetic CRS:  WGS 84
## First 4 features:
##        name                       geometry
## 1      Fiji MULTIPOLYGON (((180 -16.067...
## 2  Tanzania MULTIPOLYGON (((33.90371 -0...
## 3 W. Sahara MULTIPOLYGON (((-8.66559 27...
## 4    Canada MULTIPOLYGON (((-122.84 49,...

FIGURA 4.9: Diagrama de un marco de datos de características simples. La columna de geometría rastrea las características espaciales adjuntas a cada fila en el marco de datos.

Existen 4 formas diferentes de renderizar objetos sf con plotly: plot_ly(), plot_mapbox(), plot_geo() ya través de ggplot2geom_sf(). Estas funciones representan varios polígonos utilizando un solo trazo de forma predeterminada, lo cual es rápido pero limita la flexibilidad de variar el color de varios polígonos. Para representar varios polígonos con diferentes colores, es necesario hacerlo mediante un identificador único (como name) y usar varias trazas. El uso de varias trazas también agrega automáticamente la capacidad de filtrar a través de entradas de leyenda.

canada <- ne_states(country = "Canada", returnclass = "sf")
plot_ly(canada, split = ~name, color = ~provnum_ne)
## No trace type specified:
##   Based on info supplied, a 'scatter' trace seems appropriate.
##   Read more about this trace type -> https://plotly.com/r/reference/#scatter

FIGURA 4.10: Uso de split y color para crear un mapa de coropletas de las provincias de Canadá.

plot_ly(
  canada, 
  split = ~name, 
  color = I("gray90"), 
  text = ~paste(name, "is \n province number", provnum_ne),
  hoveron = "fills",
  hoverinfo = "text",
  showlegend = FALSE
)
## No trace type specified:
##   Based on info supplied, a 'scatter' trace seems appropriate.
##   Read more about this trace type -> https://plotly.com/r/reference/#scatter

La función Split, que muestra varios polígonos con varios trazos, es la capacidad de mostrar diferentes compensaciones de relleno para cada polígono. Figura 4.11: Use split, text y hoveron=‘fills’ para mostrar información sobre herramientas específica para cada provincia canadiense.

# filter the world sf object down to canada
canada <- filter(world, name == "Canada")
# coerce cities lat/long data to an official sf object
cities <- st_as_sf(
  maps::canada.cities, 
  coords = c("long", "lat"),
  crs = 4326
)

# A PROJ4 projection designed for Canada
# http://spatialreference.org/ref/sr-org/7/
# http://spatialreference.org/ref/sr-org/7/proj4/
moll_proj <- "+proj=moll +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 
+units=m +no_defs"

# perform the projections
canada <- st_transform(canada, moll_proj)
cities <- st_transform(cities, moll_proj)

# plot with geom_sf()
p <- ggplot() + 
  geom_sf(data = canada) +
  geom_sf(data = cities, aes(size = pop), color = "red", alpha = 0.3)
ggplotly(p)

El enfoque de mapa personalizado ( plot_ly() y geom_sf()) es más flexible ya que permite proyecciones de mapas bien definidas. Figura 4.12: Poblaciones de varias ciudades canadienses trazadas en un mapa base personalizado utilizando la proyección de Mollweide.

sum(rapply(world$geometry, nrow))
## [1] 10654
#> [1] 10586
world_large <- ne_countries(scale = "large", returnclass = "sf")
sum(rapply(world_large$geometry, nrow))
## [1] 548471
#> [1] 548121

ne_countries()esto nos da un objeto sf con más de 50 veces más coordenadas espaciales que la escala predeterminada.

4.2.2 Cartogramas Los cartogramas son una técnica que distorsiona el tamaño de los polígonos geoespaciales para codificar una variable numérica diferente del tamaño del terreno.

#library(cartogram)
#library(albersusa)

#us_cont <- cartogram_cont(usa_sf("laea"), "pop_2014")

#plot_ly(us_cont) %>% 
  #add_sf(
    #color = ~pop_2014, 
    #split = ~name, 
    #span = I(1),
    #text = ~paste(name, scales::number_si(pop_2014)),
    #hoverinfo = "text",
    #hoveron = "fills"
  #) %>%
  #layout(showlegend = FALSE) %>%
  #colorbar(title = "Population \n 2014")

El cartograma del paquete R proporciona una interfaz para varios algoritmos de cartograma populares. La Figura 4.13 muestra un cartograma de áreas continuas de la población de EE. UU. en 2014 usando un algoritmo de distorsión de lámina elástica de James A

#us <- usa_sf("laea")
#us_dor <- cartogram_dorling(us, "pop_2014")

#plot_ly(stroke = I("black"), span = I(1)) %>% 
#  add_sf(
#    data = us, 
#    color = I("gray95"),
#    hoverinfo = "none"
#  ) %>%
#  add_sf(
#    data = us_dor, 
#    color = ~pop_2014,
#    split = ~name, 
#    text = ~paste(name, scales::number_si(pop_2014)), 
#    hoverinfo = "text", 
#    hoveron = "fills"
#  ) %>%
#  layout(showlegend = FALSE)

La figura 4.14 muestra un mapa discreto de Dohring de la población de EE. UU. De Dorling, D (1996) en 2014. Este mapa no intenta conservar la forma de los polígonos (como los estados), pero usa círculos para representar cada característica geoespacial y usa el área del círculo para codificar la variable de interés (como la población).

La figura 4.15 muestra un mapa discontinuo de la población de EE. UU. Olson, JM (1976) a 2014. A diferencia del mapa de Dorling, este enfoque conserva la forma de los polígonos. La implementación de la Figura 4.15 simplemente toma la Figura 4.14 y cambia Cartogram_dorling() a Cartogram_ncont().

#library(geojsonio)
#tiles <- geojson_read("~/Downloads/tiles.topo.json", what = "sp")
#tiles_sf <- st_as_sf(tiles)
#plot_ly(tiles_sf, split = ~name)

Figura 4.16 Fotos de mosaico de la población estadounidense. en 2016 exportado directamente desde el servicio web gratuito Pitch.