Mapas de calor con Leaflet en R

En este ejemplo de código, utilizo una función de geocodificación que se encuentra en datascienceplus para geocodificar los datos de intensidad de búsqueda de tendencias de Google, comparando la tendencia de búsqueda por nombre de ciudad para «Hamburguesa» y «Pizza» en Alemania. Luego visualizo los resultados con mapas de calor, generados con el paquete Leaflet en R.

Codificación geográfica de datos de entrada mediante la API de Open Street Map

En el siguiente ejemplo de codificación, implemento la función de codificación geográfica de «datascienceplus» y la aplico usando dos DataFrames con datos de Google Trends. Los DataFrames contienen datos tabulares recuperados del servicio Google Trends, que comprenden puntuaciones de intensidad de búsqueda por nombres de ciudades alemanas para los términos de búsqueda «Hamburguesa» y «Pizza».

# implementar una función de geocodificación, usando OSM-API basada en JSON
#install.packages("jsonlite")
library(jsonlite)

# documentación: http://wiki.openstreetmap.org/wiki/Nominatim
# fuente: 
# datascienceplus.com/osm-nominatim-with-r-getting-locations-geo-coordinates-by-its-address/
osm_geocoder <- function(address = NULL)
{
  if(suppressWarnings(is.null(address)))
    return(data.frame())
  
  tryCatch(
    d <- jsonlite::fromJSON( 
      gsub('\\@addr\\@', gsub('\\s+', '\\%20', address), 
           'http://nominatim.openstreetmap.org/search/@addr@?format=json&addressdetails=0&limit=1')
    ), error = function(c) return(data.frame())
  )

  if(length(d) == 0) 
    return(data.frame())
  
  return(data.frame(lon = as.numeric(d$lon), lat = as.numeric(d$lat)))
}

# lectura de datos de entrada (archivos csv tabulares con datos de Tendencias de Google
setwd("C:/Users/Linnart/Desktop/Supply Chain Analytics/08 R coding/01__spatial visualization/Spatial food trends analysis")

# los datos de entrada comprenden la intensidad de búsqueda de Google para hamburguesas y pizzas en Alemania
input_pizza_map <- read.csv(file="Pizza on map.csv",header=TRUE,sep=",",stringsAsFactors = FALSE)
input_burger_map <- read.csv(file="Burger on map.csv",header=TRUE,sep=",",stringsAsFactors = FALSE)
#input_burger_and_pizza_map <-read.csv(file="Pizza vs Burger on map.csv",header=TRUE,sep=",",stringsAsFactors = FALSE)
#input_burger_and_pizza_timeline <- read.csv(file="Pizza vs Burger.csv",header=TRUE,sep=",",stringsAsFactors = FALSE)

# geocodificar datos de entrada, es decir, aplicar la función de codificación geográfica
input_pizza_map<-data.frame(input_pizza_map$Town.City,"Lat"=rep(NA,nrow(input_pizza_map)),"Long"=rep(NA,nrow(input_pizza_map)),input_pizza_map$Pizza...2.12.17...2.12.18.)
input_burger_map<-data.frame(input_burger_map$Town.City,"Lat"=rep(NA,nrow(input_burger_map)),"Long"=rep(NA,nrow(input_burger_map)),input_burger_map$Burger...2.12.17...2.12.18.)

# primero, geocodificar ciudades de hamburguesas
for(i in 1:nrow(input_burger_map)){
  # usa el geocodificador para geocodificar el nombre de la ciudad
  geocodes <- osm_geocoder(address=paste0(input_burger_map$input_burger_map.Town.City[i],", Germany"))
  print(input_burger_map$input_burger_map.Town.City[i])
  if(nrow(geocodes)>=1){
    input_burger_map$Lat[i] <- geocodes$lat[1]
    input_burger_map$Long[i]<- geocodes$lon[1]}
  # duerma un segundo para evitar ser prohibido por la API de OSM
  Sys.sleep(1)
}

# segundo, geocodificar ciudades de pizza
for(i in 1:nrow(input_pizza_map)){
  # usa el geocodificador para geocodificar el nombre de la ciudad
  geocodes <- osm_geocoder(address=paste0(input_pizza_map$input_pizza_map.Town.City[i],", Germany"))
  print(input_pizza_map$input_pizza_map.Town.City[i])
  if(nrow(geocodes)>=1){
    input_pizza_map$Lat[i] <- geocodes$lat[1]
    input_pizza_map$Long[i]<- geocodes$lon[1]}
  # sleep one second to avoid getting banned by OSM API
  Sys.sleep(1)
}

Después de haber geocodificado los nombres de las ciudades en los DataFrames, limpio los datos para evitar entradas y filas vacías. Para eso utilizo el paquete «dplyr» en R:

# limpieza de marcos de datos para que no se contengan valores NA
# use el paquete "dplyr" para limpiar
library(dplyr)

# aplique el paquete "dplyr" para la limpieza
cleaned_pizza_map <- input_pizza_map %>% filter(!is.na(Lat)) 
colnames(cleaned_pizza_map)<-c("City","Lat","Long","Trend")
cleaned_burger_map <- input_burger_map %>% filter(!is.na(Lat))
colnames(cleaned_burger_map)<-c("City","Lat","Long","Trend")

Mapas de calor de datos geocodificados, usando Leaflet

Después de haber geocodificado y limpiado las puntuaciones de intensidad de búsqueda de Google Trends por las principales ciudades alemanas, utilizo el paquete Leaflet en R para crear un mapa de calor. Usando el mapa de calor visualizo la distribución espacial de la intensidad de búsqueda del término de búsqueda:

# importar leflet y leaflet.extras me permitirá hacer un mapa de calor
library(leaflet)
library(leaflet.extras)
library(magrittr)

# definir el centro del mapa
lat_center <- c(cleaned_burger_map$Lat,cleaned_pizza_map$Lat) %>% as.numeric() %>% mean
long_center <- mean(c(cleaned_burger_map$Long,cleaned_pizza_map$Long)) 

# crear un mapa de calor para la intensidad de búsqueda de hamburguesas
viz_map_burger <- cleaned_burger_map %>%
  leaflet() %>% 
  addTiles() %>% 
  addProviderTiles(providers$OpenStreetMap.DE) %>% 
  setView(long_center,lat_center,6) %>%
  addHeatmap(lng=~Long,lat=~Lat,intensity=~Trend,max=100,radius=20,blur=10)

# crear un mapa de calor para la intensidad de búsqueda de pizza
viz_map_pizza <- cleaned_pizza_map %>%
  leaflet() %>% 
  addTiles() %>% 
  addProviderTiles(providers$OpenStreetMap.DE) %>% 
  setView(long_center,lat_center,6) %>%
  addHeatmap(lng=~Long,lat=~Lat,intensity=~Trend,max=100,radius=20,blur=10)

# trazar en una cuadrícula de 1x2; para eso, use el paquete "mapview" en R
#install.packages("mapview")
library(mapview)
latticeview(viz_map_burger,viz_map_pizza)

La visualización de datos espaciales en R también se puede realizar con otros paquetes, como deckgl, ggmap, ggplot2 y webglobe. Puede encontrar ejemplos de codificación relacionados con estos paquetes en mi blog.

You May Also Like

Leave a Reply

Leave a Reply

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.