Merge csv and json file in Leaflet map - strange mistake - r

Folks, I have no idea what a heck is going on. I did enough leaflet maps before and never had such problem. Shocked a little bit.
Doing very simple stuff.
Cannot match .csv and .json file by a state...
# US Adult Obesity 2016
library(rgdal)
library(sp)
library(leaflet)
library(geojsonio)
library(RColorBrewer)
library(dplyr)
# Set working directory
setwd("C:/~/App US Adult Obesity")
# Read csv
obesity <- read.csv("US Adult Obesity.csv", header = TRUE)
# Read geojson file
states <- geojson_read("gz_2010_us_040_00_500k.json", what = "sp")
View(states)
# Match data
obesity.map.2016 <- merge(states, obesity, by.x = "NAME", by.y = "State")
class(obesity.map.2016)
View(obesity.map.2016)
# Create a palette
obesity$Year.2016 <- as.numeric(as.character(obesity$Year.2016))
pal <- colorBin("Reds", c(22, 38), na.color = "#808080")
#, alpha = FALSE, reverse = FALSE)
# Create a popup
state_popup <- paste0("<strong>State: </strong>",
obesity$state,
"<br><strong>% of adult obesity in 2016: </strong>",
obesity$Year.2016)
# Create a map
leaflet(obesity.map.2016) %>%
addProviderTiles(providers$Stamen.TonerLite) %>%
setView(lng = -98.583, lat = 39.833, zoom = 4) %>%
addPolygons(color = "#444444", weight = 1,
# opacity = 0.5,
fillOpacity = 0.7,
fillColor = ~pal(obesity$Year.2016),
popup = state_popup) %>%
addLegend("bottomright", pal = pal, values = ~obesity$Year.2016,
opacity = 1,
title = "US Adult Obesity in 2016 by State")
As a result, I have Minnesota data in California. View shows that it does not match, I have 50 states + DC.
I cannot believe that I forgot how to do it.
Any hints about my stupid mistake?

Resolved personally. It looks like I screwed up with values, using them not from df, but from csv.
# US Adult Obesity 2016
library(rgdal)
library(sp)
library(leaflet)
library(geojsonio)
# Set working directory
setwd("C:/~US Adult Obesity")
# Read csv, which was created specifically
obesity <- read.csv("US Adult Obesity.csv", header = TRUE)
# Read geojson file
states <- geojson_read("gz_2010_us_040_00_500k.json", what = "sp")
# View(states)
# Shape file - cb_2016_us_state_500k.shp
# states <- readOGR(dsn = "C:/DC/IFC/My Shiny apps/App US Adult Obesity",
# layer = "cb_2016_us_state_500k",
# encoding = "UTF-8", verbose = FALSE)
# Match data
obesity.map.2016 <- merge(states, obesity, by = "NAME")
class(obesity.map.2016)
View(obesity.map.2016)
# Create a palette
obesity.map.2016$Year.2016 <- as.numeric(as.character(obesity.map.2016
$Year.2016))
pal <- colorBin("Reds", c(22, 38), na.color = "#808080")
#, alpha = FALSE, reverse = FALSE)
# Create a popup
state_popup <- paste0("<strong>State: </strong>",
obesity.map.2016$NAME,
"<br><strong>% of adult obesity in 2016: </strong>",
obesity.map.2016$Year.2016)
# Create a map
leaflet(obesity.map.2016) %>%
addProviderTiles(providers$Stamen.TonerLite) %>%
setView(lng = -98.583, lat = 39.833, zoom = 4) %>%
addPolygons(color = "#444444", weight = 1,
# opacity = 0.5,
fillOpacity = 0.7,
fillColor = ~pal(obesity.map.2016$Year.2016),
popup = state_popup) %>%
addLegend("bottomright", pal = pal, values = ~obesity.map.2016$Year.2016,
opacity = 1,
title = "US Adult Obesity in 2016 by State (%)")

Related

Data mismatch between dataset and value in the leaflet map

I'm trying to create a choropleth map in county level using leaflet R package and I actually do it. But when I check my data file and the hover text of any county I find that the values are not correct. For example check the Conejos county. Any explanation? Or a better way to process tha data and create this map without the mismatches?
Code:
library(raster)
library(leaflet)
library(tidyverse)
# Get USA polygon data
USA <- getData("GADM", country = "usa", level = 2)
### Get data
mydata <- read.csv("https://www.betydb.org/miscanthus_county_avg_yield.csv",
stringsAsFactors = FALSE) %>%
dplyr::select(COUNTY_NAME, Avg_yield)
### Check counties that exist in USA, but not in mydata
### Create a dummy data frame and bind it with mydata
mydata <- data.frame(COUNTY_NAME = setdiff(USA$NAME_2, mydata$COUNTY_NAME),
Avg_yield = NA,
stringsAsFactors = FALSE) %>%
bind_rows(mydata)
### Create a color palette
mypal <- colorNumeric(palette = "viridis", domain = mydata$Avg_yield)
leaflet() %>%
addProviderTiles("OpenStreetMap.Mapnik") %>%
setView(lat = 39.8283, lng = -98.5795, zoom = 4) %>%
addPolygons(data = USA, stroke = FALSE, smoothFactor = 0.2, fillOpacity = 0.3,
fillColor = ~mypal(mydata$Avg_yield),
popup = paste("Region: ", USA$NAME_2, "<br>",
"Avg_yield: ", mydata$Avg_yield, "<br>")) %>%
addLegend(position = "bottomleft", pal = mypal, values = mydata$Avg_yield,
title = "Avg_yield",
opacity = 1)

How to create a leaflet choropleth map of US counties

With the code below I get my dataframe with US county data
library(raster)
library(leaflet)
library(tidyverse)
# Get USA polygon data
USA <- getData("GADM", country = "usa", level = 2)
### Get data
mydata <- read.csv("https://www.betydb.org/miscanthus_county_avg_yield.csv",
stringsAsFactors = FALSE)
My object is to crate an interactive leaflet choropleth map of Avg_yield so first I fortify my USA polygon data
library(rgeos)
library(maptools)
library(ggplot2)
states.shp.f <- fortify(USA, region = "NAME_2")
Then I subset my dataset and merge it with the fortified:
mydata2<-mydata[,c("COUNTY_NAME","Avg_yield")]
colnames(mydata2)[1]<-"id"
## merge shape file with data
merge.shp.coef <- merge(states.shp.f, mydata2, by = "id")
but now I have a dataset with every county name many times and also some counties have different values of Avg_yield. Whats the proper way to process those data in order to use the leaflet code like:
leaflet() %>%
addProviderTiles("OpenStreetMap.Mapnik") %>%
setView(lat = 39.8283, lng = -98.5795, zoom = 4) %>%
addPolygons(data = USA, stroke = FALSE, smoothFactor = 0.2, fillOpacity = 0.3,
fillColor = ~mypal(mydata$Avg_yield),
popup = paste("Region: ", USA$NAME_2, "<br>",
"Avg_yield: ", mydata$Avg_yield, "<br>")) %>%
addLegend(position = "bottomleft", pal = mypal, values = mydata$Avg_yield,
title = "Avg_yield",
opacity = 1)
The propoer way to do this is to transform your polygon object into a sf object
with st_as_sf()
Here you have a working example :
(I did used some other data for the polygon, I thought yours too precise and require a lot of resources, plus I made it work with shiny)
library(leaflet)
library(tidyverse)
library(ggplot2)
library(sf)
library(shiny)
USA <- st_read(dsn = '[your path]/cb_2018_us_county_500k.shp')
### Get data
mydata <- read.csv("https://www.betydb.org/miscanthus_county_avg_yield.csv",
stringsAsFactors = FALSE)
states_sf <- st_as_sf(USA)
mydata2<-mydata[,c("COUNTY_NAME","Avg_yield")]
colnames(mydata2)[1]<-"NAME"
## merge shape file with data
states_sf_coef <- left_join(states_sf, mydata2, by = "NAME")
ui <- fluidPage(
leafletOutput("map", height = "100vh")
)
server <- function(input, output, session) {
bins <- c(0, 5, 10, 15, 20, 25, 30, 35, 40)
mypal <- colorBin("YlOrRd", domain = states_sf_coef$Avg_yield, bins = bins)
#Sortie map
output$map <- renderLeaflet({
leaflet()%>%
addProviderTiles("OpenStreetMap.Mapnik")%>%
setView(lat = 39.8283, lng = -98.5795, zoom = 4) %>%
addPolygons(
data = states_sf_coef,
fillColor = ~mypal(states_sf_coef$Avg_yield),
stroke = FALSE,
smoothFactor = 0.2,
fillOpacity = 0.3,
popup = paste("Region: ", states_sf_coef$NAME_2, "<br>",
"Avg_yield: ", states_sf_coef$Avg_yield, "<br>"))%>%
addLegend(position = "bottomleft",
pal = mypal,
values = states_sf_coef$Avg_yield,
title = "Avg_yield",
opacity = 1)
})
}
# Create Shiny app ----
shinyApp(ui = ui, server = server)

Adding an interactive filter to a layered leaflet() map in R

I have created a map that has different layers for different variables, but would like to also have a selector box that allows you to select which year you view, essentially filtering the data for that particular year.
The code below makes the map based on all years data. I'd like almost the same map, but with the ability to change what year you are viewing data for (i.e. 1990, 1991, 1992, or 1993)
# get shapefiles (download shapefiles: http://www2.census.gov/geo/tiger/GENZ2014/shp/cb_2014_us_county_5m.zip)
usgeo <- st_read("~/cb_2014_us_county_5m/cb_2014_us_county_5m.shp") %>%
mutate(fips = as.numeric(paste0(STATEFP, COUNTYFP)))
### alternatively, tweak this code so you can download data directly ####
temp <- tempfile()
download.file("http://www2.census.gov/geo/tiger/GENZ2014/shp/cb_2014_us_county_5m.zip",temp)
data <- st_read(unz(temp, "cb_2014_us_county_5m.shp"))
unlink(temp)
########################################################
# create fake data
sample <- data.frame(fips = rep(as.numeric(c("37001", "37003", "37005", "37007", "37009", "37011", "37013", "37015", "37017", "37019"), 4)),
year = c(rep(1990, 10), rep(1991, 10), rep(1992, 10), rep(1993, 10)),
life = sample(1:100, 40, replace=TRUE),
income = sample(8000:1000000, 40, replace=TRUE),
pop = sample(80000:1000000, 40, replace=TRUE))
# join fake data with shapefiles
sample <- st_as_sf(sample %>% left_join(usgeo))
# drop layers (not sure why, but won't work without this)
sample$geometry <- st_zm(sample$geometry, drop = T, what = "ZM")
# change projection
sample <- sf::st_transform(sample, "+proj=longlat +datum=WGS84")
# create popups
incomepopup <- paste0("County: ", sample$NAME, ", avg income = $", sample$income)
poppopup <- paste0("County: ", sample$NAME, ", avg pop = ", sample$pop)
lifepopup <- paste0("County: ", sample$NAME, ", avg life expectancy = ", sample$life)
# create color palettes
lifePalette <- colorNumeric(palette = "Purples", domain=sample$life)
incomePalette <- colorNumeric(palette = "Reds", domain=sample$income)
popPalette <- colorNumeric(palette = "Oranges", domain=sample$pop)
# create map
leaflet(sample) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(stroke=FALSE,
smoothFactor = 0.2,
fillOpacity = .8,
popup = poppopup,
color = ~popPalette(sample$pop),
group = "pop") %>%
addPolygons(stroke=FALSE,
smoothFactor = 0.2,
fillOpacity = .8,
popup = lifepopup,
color = ~lifePalette(sample$life),
group = "life") %>%
addPolygons(stroke=FALSE,
smoothFactor = 0.2,
fillOpacity = .8,
popup = incomepopup,
color = ~incomePalette(sample$income),
group = "income") %>%
addLayersControl(
baseGroups=c("income", "life", "pop"),
position = "bottomleft",
options = layersControlOptions(collapsed = FALSE)
)
The first map here (and screenshotted below) shows the output of what I already have (except the data is filtered for only year == 1993). I'd like that, but without the "year" variable, and instead, an additional selector box that would allow you to select which year you want data for.

How to add labels on top of polygons in leaflet

I am working with the leaflet R package. I have a zoning system made of polygons and I'd like to lay their IDs on top of them. Below is an illustration (with another software) of my objective.
Thanks for your suggestions!
Since there is no reproducible data, I decided to use one of my previous posts related to leaflet. There are two things you want to take away from this post: 1) you need to create a data frame containing center points of target regions, 2) you need to use addLabelOnlyMarkers(). You can achieve the first thing using gCentroid(). I added row names of the polygon data set (UK) as character to centers. This is used for labeling. You need to think what labels you use in your own case. Once this data set is ready, you want to use it in addLabelOnlyMarkers().
library(raster)
library(rgeos)
library(leaflet)
# Get UK polygon data
UK <- getData("GADM", country = "GB", level = 2)
# Find a center point for each region
centers <- data.frame(gCentroid(UK, byid = TRUE))
centers$region <- row.names(UK)
### Create dummy data
set.seed(111)
mydf <- data.frame(place = unique(UK$NAME_2),
value = sample.int(n = 1000, size = n_distinct(UK$NAME_2), replace = TRUE))
### Create five colors for fill
mypal <- colorQuantile(palette = "RdYlBu", domain = mydf$value, n = 5, reverse = TRUE)
leaflet() %>%
addProviderTiles("OpenStreetMap.Mapnik") %>%
setView(lat = 55, lng = -3, zoom = 6) %>%
addPolygons(data = UK,
stroke = FALSE, smoothFactor = 0.2, fillOpacity = 0.3,
fillColor = ~mypal(mydf$value),
popup = paste("Region: ", UK$NAME_2, "<br>",
"Value: ", mydf$value, "<br>")) %>%
addLabelOnlyMarkers(data = centers,
lng = ~x, lat = ~y, label = ~region,
labelOptions = labelOptions(noHide = TRUE, direction = 'top', textOnly = TRUE)) %>%
addLegend(position = "bottomright", pal = mypal, values = mydf$value,
title = "UK value",
opacity = 0.3)

How to "addTiles" on top of "addPolygons" in R's Leaflet?

How do you set the layer order in R's leaflet package so that tiles show up on top of polygons filled with color?
Here's what I've got so far:
require(leaflet)
require(acs)
require(tigris)
require(rgdal)
census.income.end.year = 2015
county = 17
nd.counties=acs.fetch(geography=geo.make(state="ND", county=county),
table.number="B01003", endyear = 2015)
tracts <- tigris::tracts(state = 'ND', county = county, cb=FALSE, year = 2015)
# create a geographic set to grab tabular data (acs)
geo<-geo.make(state=c("ND"),
county = county,
tract="*")
# add in median income
median.income <- acs.fetch(endyear = census.income.end.year,
geography = geo,
variable = c("B19013_001"))
income_df <- data.frame(paste0(as.character(median.income#geography$state),
str_pad(as.character(median.income#geography$county), 3, 'left', '0'),
str_pad(as.character(median.income#geography$tract), 5, 'left', '0')),
median.income#estimate)
rownames(income_df)<-1:nrow(income_df)
names(income_df)<-c("GEOID", "hhincome")
income_merged <- geo_join(tracts, income_df, "GEOID", "GEOID")
income_merged <- spTransform(income_merged, CRS("+init=epsg:4326"))
qpal <- colorQuantile("plasma", income_df$hhincome, n = 4)
leaflet() %>%
setView( -96.7898, 46.8772, zoom=11) %>%
addPolygons(data = income_merged,
fillColor = qpal(income_merged$hhincome),
fillOpacity = 1,
weight = 0.3) %>%
addProviderTiles(providers$Hydda.RoadsAndLabels)
Ultimately, I'ld like to do this with addTiles (instead of addProviderTiles as in the above code) using a custom MapBox, but I can't figure out how to make that reproducible for this example... given that you need a key to access custom MapBox tiles (BTW, I've created a custom MapBox tile that should be transparent except for roads and labels, so the underlying polygons should "show thru.")
Here is one way to do add a tile on top of a circle with the non-R version of leaflet: http://jsfiddle.net/dcu9pz2w/, but I don't see how to make that work in my context. I think adding "panes" may be the way to go, but I don't see that functionality in R leaflet. Also, I explored z-index values, but that seemed to be a dead end.
Any help is much appreciated!
R leaflet now includes addMapPane function. The solution to this problem is to first set up pane order and then add tiles/polygons. Reproducible example:
library(leaflet)
library(geojsonio)
# get polygon data
# https://github.com/simonepri/geo-maps/blob/master/info/countries-land.md
world <- geojson_read(
"https://github.com/simonepri/geo-maps/releases/download/v0.6.0/countries-land-10km.geo.json",
what = "sp"
)
# generate random values
world#data$value <- runif(nrow(world#data))
# get color palette
color_pal <- colorNumeric(palette = "YlOrRd", domain = NULL)
# get leaflet map
leaflet() %>%
setView(lat = 50, lng = 15, zoom = 4) %>%
addMapPane("background_map", zIndex = 410) %>% # Level 1: bottom
addMapPane("polygons", zIndex = 420) %>% # Level 2: middle
addMapPane("labels", zIndex = 430) %>% # Level 3: top
addProviderTiles(
providers$Esri.WorldTerrain,
options = pathOptions(pane = "background_map")
) %>%
addPolygons(
data = world, stroke = FALSE, smoothFactor = 0.2,
fillOpacity = 0.6, fillColor = ~color_pal(value),
options = pathOptions(pane = "polygons")
) %>%
addProviderTiles(
providers$Stamen.TonerLabels,
options = pathOptions(pane = "labels")
)

Resources