GeoData
Conviértete en Geohacker
¿Qué es OSM?
En la mayoría de los países la información geográfica pública no es de libre uso. Al no estar considerada por las administraciones públicas como un servicio similar a una infraestructura de orden público, el usuario paga dos veces por esa información, la primera al generarla, a través de sus impuestos, y la segunda al adquirirla para su uso.
Así mismo, las licencias de uso a veces restringen su utilización al tener el usuario un derecho limitado de aplicación de la cartografía. No se puede corregir errores, añadir nuevos datos o emplear esos mapas de determinados modos (integración en aplicaciones informáticas, publicaciones, etc.) sin pagar por ellos.
OpenStreetMap es un proyecto abierto, social y de dimensiones gigantescas elaborado por personas normales.
Los mapas se crean utilizando información geográfica capturada con dispositivos GPS móviles, ortofotografías y otras fuentes libres. Esta cartografía, tanto las imágenes creadas como los datos vectoriales almacenados en su base de datos, se distribuyen bajo licencia abierta Open Database License (ODbL).nota 2
El nombre del proyecto es OpenStreetMap una sola palabra designa una única base de datos que abarca todo el mundo. A veces se le llama erróneamente Open Street Map o peor OpenStreetMaps. -Sergio Sevillano, cofundador de OSM España
¿Qué es un GeoHacker?
¿Qué son los Geodatos?
Los geodatos son información acerca de ubicaciones geográficas almacenadas en un formato que se puede usar con un sistema de información geográfica (SIG).
Los geodatos se pueden almacenar en una base de datos, geodatabase, shapefile, cobertura, imagen de ráster o incluso en una tabla dbf u hoja de cálculo de Microsoft Excel. La siguiente es una lista de geodatos que se puede usar con el software SIG de Esri junto con vínculos a temas que los describen:
¿Qué son R?
R es un entorno y un lenguaje de programación enfocado en el análisis estadístico de los más utilizados en el campo de la minería de datos que pueden aplicarse a gran variedad de disciplinas.
Este lenguaje forma parte de GNU y se distribuye bajo licencia GNU GLP.
¿Qué son RStudio?
RStudio es un entorno de desarrollo integrado (IDE) para el lenguaje de programación R, dedicado a la computación estadística y gráficos. Incluye una consola, editor de sintaxis que apoya la ejecución de código, así como herramientas para el trazado, la depuración y la gestión del espacio de trabajo.
¿Qué son Leaflet?
Leaflet es una librería open-source JavaScript que permite crear mapas interactivos para la web y para entorno móvil de manera fácil. Pesa apenas unos 33 KB.
Con esta biblioteca podemos usar mapas base de Google, ESRI, OpenStreetMap, entre otros, agregar marcadores, polígonos, líneas, realizar zoom y extender su funcionalidad con una buena cantidad de plugins, entre ellos, muchos desarrollados por ESRI.
Empresas como Flickr, Facebook, CartoDB, Washington Post y OpenSteetMap hacen uso de Leaflet.
var map = L.map('map').setView([6.241127, -75.560000], 13);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
Inicio
- Instalación de Rstudio
- Instalación de la paquetería de Leaflet
- Descargar los archivos de este repositorio
Map Components
-
The
leaflet
map object (SVG). -
Tile Layers. 1
-
Vector Data Layers (points, lines, circles, rectangles, polygons).
-
Raster Data Layers.
-
Popups and labels.
-
Controls (zoom control, layer control, buttons, attribution, legends).
-
Custom controls and layers via lots and lots of plugins.
.footnote[ [1] How web maps work. ]
Advanced Concepts
-
Visualizations are organized into various panes. Different panes have different zIndex for overlay.
-
Events are emitted for various actions and can be acted upon by registering event listeners for appropriate events.
-
Data can be organized into groups which allows bulk operations on grouped data.
-
Many 3rd-Party vendors (commercial and open-source) provide add-ons on top of Leaflet. e.g. ESRI, Mapbox, GIBs.
class: inverse, center, middle
BEGINNER
Building a Map
leaflet(data) | leafletProxy() %>%
setView(lat, lon, zoom) # Initial View OR
fitBounds(lat_se, lon_se, latnw, lon_nw) # Initial Bounds
setMaxBounds(lat_se, lon_se, latnw, lon_nw) # Max Bounds
addTiles() | addProviderTiles() | addWMSTiles() #Tiles
addMarkers() | addCircleMarkers() |
addAwesomeMarkers() | addLabelOnlyMarkers() # Markers
addPolylines() | addCircles() |
addRectangles() | addPolygons() # Shapes
addRasterImage(image) # Raster Data
addLegend() | addLayersControl() | addControl() # Controls
.footnote[
-
A Map is built by piping (
%>%
) several add* methods. -
leaflet()
/addXXX()
methods take an optionaloptions
argument for customization. ]
Minimal Example
library(leaflet)
leaflet()
leaflet() %>%
frameWidget(height='275')
Wait, What? Where's my map?
Tiles
leaflet() %>%
addTiles()
leaflet() %>%
addTiles() %>% setMapWidgetStyle() %>%
frameWidget(height='275')
- Defaults to OpenStreetMap tiles. Custom URL can be provided via the
urlTemplate
param. tileOptions()
can be used for customizing the tile layer.
Provider Tiles
leaflet() %>%
addProviderTiles(providers$CartoDB.DarkMatter, group="Dark") %>%
addProviderTiles(providers$CartoDB.Positron, group="Light") %>%
addLayersControl(baseGroups=c('Dark','Light'))
leaflet() %>%
addProviderTiles(providers$CartoDB.DarkMatter, group="Dark") %>%
addProviderTiles(providers$CartoDB.Positron, group="Light") %>%
addLayersControl(baseGroups=c('Dark','Light')) %>%
setMapWidgetStyle() %>%
frameWidget(height='275')
There are more than 100 tile providers available via the providers
list.
Markers
-
Represent unique locations on the map.
-
Added using
addMarkers
,addCircleMarkers
,addAwesomeMarkers
,addLabelOnlyMarkers
. -
Input can be vectors of lat/lon coordinates, data.frame,
sp::SpatialPoints
,sp::SpatialPointsDataFrame
. -
Can have labels, and popups whose content can be derived from the data.
-
Can be toggled using grouping.
-
Can be clustered for better performance and visual aesthetics.
Adding Markers
leaflet(data) %>%
addMarkers(
lat = ~latitude, lon = ~longitude,
options = markerOptions(),
label=~label, labelOptions = labelOptions(),
popup=~popup, popupOptions = popupOptions(),
clusterOptions = clusterOptions(),
group = 'Group-A')
# Similarly
addCircleMarkers() # Fixed scale Circles
addAwesomeMarkers() # More choices for icons
addLabelOnlyMarkers() # No icon
Markers Example
quakes.df <- quakes %>% dplyr::mutate(
mag.level = cut(mag,c(3.5,4.5,5.5,6.5),
labels = c('> 3.5 & <=4.5', '>4.5 & <=5.5', '>5.5 & <=6.5'))) %>%
split(.$mag.level)
l <- leaflet() %>%
addProviderTiles(providers$Esri.OceanBasemap)
names(quakes.df) %>%
purrr::walk( function(df) {
l <<- l %>%
addMarkers(data=quakes.df[[df]], lng=~long, lat=~lat,
label=~as.character(mag), popup=~as.character(mag),
group = df,
clusterOptions = markerClusterOptions())
})
l <- l %>%
addLayersControl(
overlayGroups = names(quakes.df),
options = layersControlOptions(collapsed = FALSE)) %>%
addMiniMap(tiles = providers$Esri.OceanBasemap, width = 120, height=80)
Markers Example
l %>%
frameWidget(height='440')
Shapes
-
Can be lines, circles, rectangles, polygons.
-
Added using
addPolyLines
,addCircles
,addRectangles
, andaddPolygons
. -
For polylines: Input can be
sp::Lines
,sp::SpatialLines
,sp::SpatialLinesDataFrame
. -
For polygons: Input can be
sp::Polygons
,sp::SpatialPolygons
,sp::SpatialPolygonsDataFrame
. -
Can have labels and popups whose content can be derived from data.
-
Can have their appearance customized using data.
-
Can be grouped for bulk operations.
-
Can be highlighted on mouse-over.
Adding Shapes
leaflet(data) %>%
addPolygons(
label=~label, labelOptions = labelOptions(),
popup=~popup, popupOptions = popupOptions(),
# Shape Options
options = pathOptions(),
weight = 1, opacity=0.8, color = "#000000",
fillColor="#ff0000", fillOpacity=0.7,
# Highlighting on mouse-over
highlightOptions = highlightOptions(
color='#00ff00', weight = 2,
opacity = 1, fillOpacity = 1,
bringToFront = TRUE, sendToBack = TRUE),
group = 'Group-A')
#Similarly
addCircles()
addPolylines()
addRectangles()
Shapes Example
library(magrittr)
fName <- 'world-population.geo.json'
spdf <- geojsonio::geojson_sp(rmapshaper::ms_simplify(readr::read_file(fName)))
spdf@data %<>% dplyr::mutate(
AREA = as.numeric(as.character(AREA)),
POP2005 = as.numeric(as.character(POP2005))
)
spdf <- subset(
spdf,
!(is.na(AREA) | AREA <1 | is.na(POP2005) | POP2005<1)
)
spdf@data %<>%
dplyr::mutate(
POPDENSITY = POP2005/AREA
)
spdf.world <- spdf
# spdf is a sp::SpatialPolygonsDataFrame
qpal <- colorQuantile(rev(viridis::viridis(5)),
spdf$POPDENSITY, n=5)
l <- leaflet(spdf, options =
leafletOptions(attributionControl = FALSE, minzoom=1.5)) %>%
addPolygons(
label=~stringr::str_c(
NAME, ' ',
formatC(POPDENSITY, big.mark = ',', format='d')),
labelOptions= labelOptions(direction = 'auto'),
weight=1,color='#333333', opacity=1,
fillColor = ~qpal(POPDENSITY), fillOpacity = 1,
highlightOptions = highlightOptions(
color='#000000', weight = 2,
bringToFront = TRUE, sendToBack = TRUE)
) %>%
addLegend(
"topright", pal = qpal, values = ~POPDENSITY,
title = htmltools::HTML("Population Density<br/>(2005)"),
opacity = 1 )
Shapes Example
l %>% setMapWidgetStyle() %>%
frameWidget(height='400', width='95%')
- Performance Tip: Use
rmapshaper::ms_simplify
with impunity!
Other Misc. Stuff
-
addRasterImage
for adding raster image data. Example. -
addMiniMap
for a small map inside the main map at a zoom offset. Example. -
addMeasure
to measure distances/area. Example. -
addGraticule
adds a graticule. Example. -
addEasyButton
/addEasyButtonBar
for customized buttons Example. -
addControl
for custom Control element. -
addScaleBar
to display a scale.
class: inverse, center, middle
INTERMEDIATE
Projections
-
ALL MAPS OF EARTH ARE WRONG! Obligatory XKCD ref.
-
By Default leaflet ...
-
Which means ...
-
You can't use tile services which provide tiles in non-spherical-Mercator projections.
-
You need to convert any vector/raster data in any non-epsg:4326 to epsg:4326 before adding to the leaflet map.
-
Proj4Leaflet
-
Enter Proj4Leaflet a leaflet plugin allowing use of proj4js to display map in non-spherical-Mercator projection.
-
Basic use
leaflet(options =
leafletOptions(crs = leafletCRS()))
-
So now you can display data/tiles in a non-spherical-Mercator projection.
-
But you still need to specify vector/raster data in EPSG:4326 (lat/lon) which will get internally converted to the custom projection specified.
-
Another caveat: You can have only one projection at a time which is set during initialization. To change projection you need to destroy and rebuild the map.
Projections Example 1.
spdf <- spdf.world
crs.molvidde <- leafletCRS(
crsClass="L.Proj.CRS", code='ESRI:53009',
proj4def= '+proj=moll +lon_0=0 +x_0=0 +y_0=0 +a=6371000 +b=6371000 +units=m +no_defs',
resolutions = c(65536, 32768, 16384, 8192, 4096, 2048))
l <- leaflet(
spdf,
options = leafletOptions(
maxZoom = 5, crs= crs.molvidde, attributionControl = FALSE)) %>%
addGraticule(style= list(color= '#999', weight= 0.5, opacity= 1)) %>%
addGraticule(sphere = TRUE,
style= list(color= '#777', weight= 1, opacity= 0.25)) %>%
addPolygons(
label=~stringr::str_c(
NAME, ' ', formatC(POPDENSITY, big.mark = ',', format='d')),
labelOptions= labelOptions(direction = 'auto'),
weight=1,color='#ffffff', opacity=1,
fillColor = ~qpal(POPDENSITY), fillOpacity = 1,
highlightOptions = highlightOptions(
color='#000000', weight = 2,
bringToFront = TRUE, sendToBack = TRUE))
Projections Example 1.
l %>%
setView(10,0,0.5) %>% setMapWidgetStyle() %>%
frameWidget(height='440')
Projections Example 2.
spdf <- rmapshaper::ms_simplify(albersusa::usa_composite())
pal <- colorNumeric(palette = "Blues", domain = spdf@data$pop_2014)
crs.laea <- leafletCRS(
crsClass="L.Proj.CRS", code='EPSG:2163',
proj4def='+proj=laea +lat_0=45 +lon_0=-100 +x_0=0 +y_0=0 +a=6370997 +b=6370997 +units=m +no_defs',
resolutions = c(65536, 32768, 16384, 8192, 4096, 2048,1024, 512, 256, 128))
l <- leaflet(
options= leafletOptions(
worldCopyJump = FALSE, crs=crs.laea, attributionControl = FALSE)) %>%
addPolygons(
data=spdf, label=~stringr::str_c(
name, ' ', formatC(pop_2014, big.mark = ',', format='d')),
labelOptions= labelOptions(direction = 'auto'),
weight = 1, color = "#000000",
fillColor=~pal(pop_2014), fillOpacity=0.7,
highlightOptions = highlightOptions(
color='#ff0000', opacity = 1, weight = 2, fillOpacity = 1,
bringToFront = TRUE, sendToBack = TRUE))
Projections Example 2.
l %>%
fitBounds(-125, 24 ,-75, 45) %>%
setMaxBounds(-125, 24 ,-75, 45) %>%
setMapWidgetStyle() %>%
frameWidget(height='400')
Projections Example 3.
suppressPackageStartupMessages(library(tilegramsR))
states <- FiveThirtyEightElectoralCollege.states@data$state
factpal <- colorFactor(
colormap::colormap(nshades = length(states),
colormap = colormap::colormaps$jet ),
states)
l <- leaflet(
options=leafletOptions(
crs = leafletCRS("L.CRS.Simple"),
minZoom = -2, maxZoom = -2,
dragging = FALSE, zoomControl = FALSE, attributionControl = FALSE)) %>%
addPolygons(
data=FiveThirtyEightElectoralCollege,
weight=1,color='#000000', fillOpacity = 0.5, opacity=0.2,
fillColor= ~factpal(state)) %>%
addPolygons(
data=FiveThirtyEightElectoralCollege.states, group = 'states',
weight=2,color='#000000',
fill = T, opacity = 1, fillOpacity = 0,
highlightOptions = highlightOptions(weight = 4)) %>%
addLabelOnlyMarkers(
data=FiveThirtyEightElectoralCollege.centers,
label = ~as.character(state),
labelOptions = labelOptions(
noHide = 'T', textOnly = T,
offset=c(-8,-20), textsize = '12px'))
Projections Example 3
l %>%
leaflet.extras::setMapWidgetStyle() %>%
setMapWidgetStyle() %>%
frameWidget(height='450')
Shiny
-
Use
leafletProxy()
to update already existing map. -
Use
clear*
methods to remove stuff already on a map. -
leaflet package traps many leaflet events and makes then available as shiny events.
-
Use
observeEvent(input$<MAP_ID>_<EVENT_NAME>)
to act on these events.
leaflet.extras
-
R package that enhances the
leaflet
package. Developed by yours truly to integrate the plethora of leaflet plugins available.1 -
Not yet on CRAN.
devtools::install_github('bhaskarvk/leaflet.extras')
-
Actively being developed and maintained. Contributions welcome.
-
leaflet
package will be stable andleaflet.extras
will be very dynamic.
.footnote[ [1] I also have leaflet.esri and leaflet.mapbox packages under heavy development. ]
leaflet.extras
-
Add/Modify/delete/style markers/shapes using Leaflet.Draw.
-
Add GeoJSON, TopoJSON, KML, GPX, CSV files directly.
- Customizable Markers and Shapes
- Choropleths from polygon data w/ auto legends and bi-directional highlighting
- Popup showing properties in a tables
-
Create Heatmap from point data.
-
Search Markers. Geo-locate using OSM Nominatum API.
-
Tiles Caching, GPS, and many more!
TopoJSON Example
library(leaflet.extras)
fName <- 'crimes_by_district.topojson'
l <- leaflet() %>%
addBootstrapDependency() %>%
setView(-75.14, 40, zoom = 11) %>%
addProviderTiles(providers$CartoDB.Positron) %>%
addGeoJSONChoropleth(
readr::read_file(fName), valueProperty ='incidents',
scale = 'OrRd', mode='q', steps = 5, padding = c(0.2,0),
popupProperty = propstoHTMLTable(
props = c('dist_numc', 'location', 'incidents', '_feature_id_string'),
table.attrs = list(class='table table-striped table-bordered'),drop.na = T),
labelProperty = JS('function(feature){return "WARD: " + feature.properties.dist_numc;}'),
color='#ffffff', weight=1, fillOpacity = 0.7,
highlightOptions = highlightOptions(
fillOpacity=1, weight=2, opacity=1, color='#000000',
bringToFront=TRUE, sendToBack = TRUE),
legendOptions = legendOptions(title='Crimes', position='topright'))
TopoJSON Example
l %>%
frameWidget(height='450')
class: inverse, center, middle
ADVANCED
Mostly for leaflet devs.
Under the hood!
-
Not your grandpa's htmlwidget!
-
Source code organization
leaflet
|_R - Contains R files
|_javascript/src - contains JS binding code written in ES2015.
|_inst/_htmlwidgets/
|_leaflet.js - JS binding file transpiled from ES2015 files.
|_leaflet.yml - widget YAML file
|_lib/ - leaflet JS files + some plugins
|_plugins/ - some more plugins
|_examples/ - more examples than you can care for!
- You need Node.js and NPM for building.
# Do this onetime
npm install -g grunt-cli
cd leaflet && npm install
grunt build # Do this everytime you change javascript/src files.
Important files
R
|_leaflet.R - Widget initializing code
|_layers.R - add/remove layers (tiles/markers/shapes)
|_normalize.R - Data normalization/extraction
|_colors.R - Color generation code
|_shiny.R - Shiny stuff
|_utils.R - odds-n-ends
|_plugin*R - R code for misc plugins
javascript/src
|_index.js - Widget initialization JS code.
|_methods.js - LeafletWidget.methods object
|_dataframe.js - JS eq. of a R data.frame
|_layer-manager.js - Manages layers
|_crs_utils.js - projections support
|_cluster-layer-store.js - Marker clustering
|_util.js - odds-n-ends
Important R functions
-
derivePoints
/derivePolygons
- extracts coordinates from various types of data. -
resolveFormula
- extracts values for various params from data using formulas. e.g.addMarkers(data=df, lat=~lat, lon=~lon, label=~name)
. -
filterNULL
- removes NULLs from list. Very useful! -
getMapData
- retrieves map data stored in theleaflet()
instance. -
invokeMethod
- Calls a JS method defined inLeafletWidget.methods
JS Object. -
htmlwidgets::onRender
- Used to invoke custom JS code after the map has been initialized.
THANK YOU!
@alexfuser
Twitter:alexfuser
LinkedIn:alexfuser
Github:Aquí encontrarás uso de datos abiertos, análisis de datos geoespaciales, desarrollo de software, visualización de datos, y cartografía.
Pasa a la Wiki para ver el contenido: https://github.com/rodowi/geo-is-osm/wiki