I am trying to create a leaflet map that adds and removes a polygon layer (SpatialDataFrame) based on changing user inputs into a flexdashboard Shiny App. The geometry of the polygons (4201 polygons) remains constant, but as user makes changes to inputs, the data set (2100500 records total) that merges with each polygon changes (to =4201 to merge with polygons).
I've been following the Leaflet R docs here https://rstudio.github.io/leaflet/shiny.html
And my sample code below seems to mimic the observe() event recommend to wrap around the addPolygons(). I've also looked at the source code from a number of similar Shiny apps from the shiny gallery page (particularly this one: https://walkerke.shinyapps.io/neighborhood_diversity/) but it doesn't seem to work
Here is a sample of the app, note the data are too large to load but see the comments. When I create the addPolygons() in the first leaflet() call, it works fine. The downside of this approach is that it causes the entire map to redraw when user input changes. Following leaflet documentation suggestion I then want to move this addPolygon into a separate observer. This is where it fails.
---
title: "Model Result Viewer"
output:
flexdashboard::flex_dashboard:
orientation: columns
vertical_layout: fill
runtime: shiny
---
```{r setup, include=FALSE}
library(flexdashboard)
library(...)
df <- fread("./data/rca_do_salt_1day.csv")
# get the unique parameters & layers
model_params <- unique(df$Parameter)
model_layers <- unique(df$Cell_K)
# read in the grid
grid <- spTransform(readOGR(dsn="./PVSC06_Grid", layer="PVSC06_WGS84"),
CRS("+proj=longlat +datum=WGS84 +no_defs"))
# Data Controls --------------------------------
<USER INPUTS SIMILAR TO:
# parameter selection
selectInput("param", "Parameter", model_params, selected = model_params[1])
#layer selection
selectInput("lyr", "Layer", model_layers, selected = model_layers[1])
# make the grid dataframe
df_subset <- reactive({
filter(df, Cell_K == input$lyr, Parameter == input$param, Time == input$timeslider)
})
# THIS MAKES THE POLYGONS FOR MAPPING
sp.grid <- reactive({
merge(grid, df_subset(), by.x = "Id", by.y = "Id")
})
# helpers for leaflet
pal <- reactive({
colorNumeric(
palette = input$colors, #"YlOrRd",
domain = df_parameter()$Value
)
})
#Set labels for grid hover
labels <- reactive({
sp.grid()$Value %>% lapply(htmltools::HTML)
})
output$map <- renderLeaflet({
leaflet() %>%
# Base Setup
addTiles(group = "Open Street Map") %>%
addProviderTiles('Esri.WorldImagery', group = "Satellite Imagery") %>%
addDrawToolbar(
targetGroup='Draw',
editOptions = editToolbarOptions(selectedPathOptions = selectedPathOptions())
) %>%
clearShapes() %>%
fitBounds(grid#bbox[1], grid#bbox[2], grid#bbox[3], grid#bbox[4]) %>%
# ================ THIS WORKS HERE, BUT NOT IN AN OBSERVER?!!! =================
# addPolygons(data = sp.grid(),
# layerId = ~Id,
# group= "Grid",
# weight = 0.1,
# opacity = 0,
# fillOpacity = 1,
# stroke = FALSE,
# fillColor = ~pal()(Value),
# highlightOptions = highlightOptions(color = "white",
# weight = 2,
# bringToFront = TRUE),
# label = labels(),
# labelOptions = labelOptions(style = list("font-weight" = "normal", padding = "3px 8px"),
# textsize = "15px",
# direction = "auto")) %>%
# # Legend
# addLegend(position = 'bottomright',
# pal = pal(), opacity = 1,
# values = sp.grid()$Value,
# title = input$param) %>%
#==================================================================================
# TOC Box
addLayersControl(
baseGroups = c("Satellite Imagery", "Open Street Map"),
overlayGroups = c("Grid", "Loads", "Draw"),
options = layersControlOptions(collapsed=TRUE)
)
})
# =============== THIS DOESN"T WORK ======================
observe({
req(sp.grid()) # this alone will cause the error
# why doesn't this work?
leafletProxy('map', data = sp.grid()) %>%
removeShape(~Id) %>%
addPolygons(
layerId = ~Id,
group= "Grid",
weight = 0.1,
opacity = 0,
fillOpacity = 1,
fill = TRUE,
stroke = FALSE,
fillColor = ~pal()(Value),
highlightOptions = highlightOptions(color = "white",
weight = 2,
bringToFront = TRUE),
label = labels(),
labelOptions = labelOptions(style = list("font-weight" = "normal", padding = "3px 8px"),
textsize = "15px",
direction = "auto")
)
})
# === THIS IS JUST EXAMPLE OF Observer that DOES work?!
# Click event for the map (will use to generate chart)
click_element <- eventReactive(input$map_shape_click, {
input$map_shape_click$id
})
# highlight the clicked element
observe({
req(click_element()) # do this if click_element() is not null
# Add the clicked element to the map in aqua, and remove when a new one is clicked
map <- leafletProxy('map') %>%
removeShape('element') %>%
addPolygons(data = sp.grid()[sp.grid()$Id == click_element(), ],
fill = TRUE,
color = '#00ffff', opacity = 1, layerId = 'element')
})
leafletOutput('map')
When I run this code, the Rmarkdown console gives error of something like and immediately crashes:
Error in : Result must have length 2100500, not 0
90 <Anonymous>
Note the actual number (90) varies but it is usually always >85 and it is the only line output in the Rmarkdown console.
Noteworthy: The 2100500 is the number of records in my non-spatial dataframe (that is filtered by user inputs and merged with spatial polygon (4201 polygons).
Therefore, it looks like the filtering isn't applying correctly, but then how come this works when i simply move it into the leaflet() call?
Related
I would like users to be able to change the choropleth map overlay by selecting different attributes from a dropdown. The map and different attributes render fine based on user selection, but the popup option of the addPolygons function does not interpret the input values the same as the rest of the app.
For below, assume we are using an object of class 'sf' named densitydata with columns for the polygon geography and the different densities to be mapped (dens1, dens2 and dens3). I want the popup to return the values of the selected density for the clicked feature. E.g. "Selected density: 1.23" but instead get the name of the column: "Selected density: dens1".
If I put the input in a mathematical function like round(), I get an error that I'm providing a non-numeric value to a mathematical function:
popup = ~paste0("<b>Selected density:</b> ", round(input$densities, 2))
Dropdown menu:
dashboardSidebar(
selectInput(inputId = "densities", label = "Select attribute",
choices = c("Density 1" = "dens1",
"Density 2" = "dens2",
"Density 3" = "dens3"), selected = NULL, multiple = F, selectize = TRUE, width = '500px', size = NULL),
Rendering the map in the server function:
output$DensMap <- renderLeaflet({
# Define palette for new selection
DensPal <- colorQuantile(palette = "YlOrRd",
domain = {densitydata %>%
pull(input$densities)},
n = 5)
# Render map
leaflet(data = densitydata) %>%
addTiles() %>% # Add default OpenStreetMap map tiles
addPolygons(fillColor = ~DensPal({densitydata %>% pull(input$densities)}),
fillOpacity = 0.5,
weight = 2,
popup = ~paste0("<b>Selected density:</b> ", input$densities) %>%
addLegend(pal = DensPal,
values = {densitydata %>% pull(input$densities)},
opacity=0.7,
title = "Legend title here",
position = "bottomleft" )
} )
You can not use input$densities directly, you can use it thru densitydata[[input$densities]]:
output$DensMap <- renderLeaflet({
# Define palette for new selection
DensPal <- colorQuantile(palette = "YlOrRd",
domain = densitydata[[input$densities]],
n = 5)
# Render map
leaflet(data = densitydata) %>%
addTiles() %>% # Add default OpenStreetMap map tiles
addPolygons(fillColor = ~DensPal(densitydata[[input$densities]]),
fillOpacity = 0.5,
weight = 2,
popup = ~paste0("<b>Selected density:</b> ",
densitydata[[input$densities]]) %>%
addLegend(pal = DensPal,
values = densitydata[[input$densities]],
opacity=0.7,
title = "Legend title here",
position = "bottomleft" )
} )
I am in the process of creating an R flexdashboard. The dashboard contains several maps for Bangladesh, which are linked to a (Highcharts) chart that is activated by clicking on a polygon (e.g. region). I am able to make it work for one page. However, if I set it up for two pages, things no longer work.
It seems that flexdashboard (at least how I set it up) is not able to handle two input$map_shape_click operations at the same time. At the moment it only works on the first page, while the map does not react on the second page although a figure is produced. I welcome any suggestions to make this work.
Below a reproducible example. Note that (1) I omitted the flexdashboard yaml in the example and (2) markdown used by stackoverflow automatically renders the first, second and third header level. They render differently when run in flexdasboard (i.e. A Large Header is a new page in flexdashboard).
# Packages
library(tidyverse)
library(raster)
library(sf)
library(highcharter)
library(leaflet)
library(htmltools)
# Get data
adm1 <- getData('GADM', country='BGD', level=1)
adm1 <- st_as_sf(adm1)
# Create dummy data.frames with link to polygon
df1 <- data.frame(NAME_1 = adm1$NAME_1,
value_1 = c(1:7))
df2 <- data.frame(NAME_1 = adm1$NAME_1,
value_2 = c(8:14))
Page 1
Column {data-width=350}
Map 1
# MAIN MAP --------------------------------------------------------------------------------
output$map <- renderLeaflet({
# Base map
leaflet() %>%
addTiles(group = "OpenStreetMap") %>%
clearShapes() %>%
addPolygons(data = adm1,
smoothFactor = 0,
color = "black",
opacity = 1,
fillColor = "transparent",
weight = 0.5,
stroke = TRUE,
label = ~htmlEscape(NAME_1),
layerId = ~NAME_1,
)
})
leafletOutput('map')
# REGION SELECTION -----------------------------------------------------------------------
# Click event for the map to draw chart
click_poly <- eventReactive(input$map_shape_click, {
x <- input$map_shape_click
y <- x$id
return(y)
}, ignoreNULL = TRUE)
observe({
req(click_poly()) # do this if click_poly() is not null
# Add the clicked poly and remove when a new one is clicked
map <- leafletProxy('map') %>%
removeShape('NAME_1') %>%
addPolygons(data = adm1[adm1$NAME_1 == click_poly(), ],
fill = FALSE,
weight = 4,
color = '#d01010',
opacity = 1,
layerId = 'NAME_1')
})
Column {data-width=350}
Plot 1
data <- reactive({
# Fetch data for the click poly
out <- df1[df1$NAME_1 == click_poly(), ]
print("page 1") # print statement to show which click_poly is used
return(out)
})
output$plot <- renderHighchart({
req(data()) # do this if click_poly() is not null
chart <- highchart() %>%
hc_chart(type = 'column') %>%
hc_legend(enabled = FALSE) %>%
hc_xAxis(categories = c('A'),
title = list(text = 'Title 1')) %>%
hc_yAxis(title = list(text = 'Value 1')) %>%
hc_plotOptions(series = list(dataLabels = list(enabled = TRUE))) %>%
hc_add_series(name = 'Series',
data = c(data()$value_1)) %>%
hc_add_theme(hc_theme_smpl()) %>%
hc_colors(c('#d01010'))
})
highchartOutput('plot')
Page 2
Column {data-width=350}
Map 2
# MAIN MAP --------------------------------------------------------------------------------
output$map2 <- renderLeaflet({
# Base map
leaflet() %>%
addTiles(group = "OpenStreetMap") %>%
clearShapes() %>%
addPolygons(data = adm1,
smoothFactor = 0,
color = "black",
opacity = 1,
fillColor = "transparent",
weight = 0.5,
stroke = TRUE,
label = ~htmlEscape(NAME_1),
layerId = ~NAME_1,
)
})
leafletOutput('map2')
# REGION SELECTION -----------------------------------------------------------------------
# Click event for the map to draw chart
click_poly2 <- eventReactive(input$map_shape_click, {
x <- input$map_shape_click
y <- x$id
return(y)
}, ignoreNULL = TRUE)
observe({
req(click_poly2()) # do this if click_poly() is not null
# Add the clicked poly and remove when a new one is clicked
map <- leafletProxy('map2') %>%
removeShape('NAME_1') %>%
addPolygons(data = adm1[adm1$NAME_1 == click_poly2(), ],
fill = FALSE,
weight = 4,
color = '#d01010',
opacity = 1,
layerId = 'NAME_1')
})
Column {data-width=350}
Plot 2
data2 <- reactive({
# Fetch data for the click poly
out <- df2[df2$NAME_1 == click_poly2(), ]
print("page 2") # print statement to show which click_poly is used
return(out)
})
output$plot2 <- renderHighchart({
req(data2()) # do this if click_poly() is not null
chart <- highchart() %>%
hc_chart(type = 'column') %>%
hc_legend(enabled = FALSE) %>%
hc_xAxis(categories = c('A'),
title = list(text = 'Title 2')) %>%
hc_yAxis(title = list(text = 'Value 2')) %>%
hc_plotOptions(series = list(dataLabels = list(enabled = TRUE))) %>%
hc_add_series(name = 'Series',
data = c(data2()$value_2)) %>%
hc_add_theme(hc_theme_smpl()) %>%
hc_colors(c('#d01010'))
})
highchartOutput('plot2')
In your click_poly2 <- eventReactive(input$map_shape_click, you have click_poly2 being the 2nd map, but you have the same map_shape_click, what if you made it map_shape_click2, hopefully flexdashboard will handle it differently as now they are 2 different maps
I figured out the answer myself following a similar question I found somewhere else. As I am quite new to shiny and based my code on examples I found, I did not realize that 'map_shape_click' applies 'shape_click' on 'map' where 'map' corresponds with the map in output$map. As I have two maps: map and map2, the eventReactive statement for page2 should be changed into
click_poly2 <- eventReactive(input$map2_shape_click, {
x <- input$map2_shape_click
y <- x$id
return(y)
}, ignoreNULL = TRUE)
Now responding to a shape_click on map2
I posted a similar question here:
How do I create a Leaflet Proxy in observeEvent() for checkboxGroup in R Shiny .
But I'm a little desperate for answers, so I thought I'd rephrase my question and post it again. I've scoured the internet for answers and can't seem to find what I'm looking for. Apologies for the double posting.
Here's my issue.
I have a dataset here:
https://github.com/mallen011/Leaflet_and_Shiny/blob/master/Shiny%20Leaflet%20Map/csv/RE.csv
It's recycling centers in Kentucky. It's set up so each recyclable material is a column, and each row i.e. recycling center is listed as yes/no as to whether each center actually recycles said material.
Here's an example of what the data looks like, in case you can't access the csv. Top row is the header column. Sorry for the formatting:
Name___________________GL______AL_____PL
Bath Community Recycling___Yes_____No____Yes
Ted & Sons Scrap Yard______No______No____Yes
Now I have the csv visualized on a R shiny dashboard app like here using Leaflet:
https://github.com/mallen011/Leaflet_and_Shiny/blob/master/Shiny%20Leaflet%20Map/re_map.png
But I want to add a control in which users can filter through where they can recycle their goods, namely, I want to use checkboxGroupInput() in R shiny so users can check materials and have recycling centers populate the map. For example, if a person wants to know where to recycle their glass, they can check "glass" in the checkbox group, and all recycling centers that allow glass recycling pop up.
So in R Shiny, I've read my recycling data csv (RE.csv):
RE <- read.csv("C:/Users/username/Desktop/GIS/Shiny Leaflet Map/csv/RE.csv")
RE$y <- as.numeric(RE$y)
RE$x <- as.numeric(RE$x)
RE.SP <- SpatialPointsDataFrame(RE[,c(7,8)], RE[,-c(7,8)])
Here's my UI that puts the checkboxGroupInput() in the sidebar():
ui <- dashboardPage(
skin = "blue",
dashboardHeader(titleWidth = 400, title = "Controls"),
dashboardSidebar(width = 400
#here's the checkboxgroup, it calls the columns for glass, aluminum and plastic from the RE.csv, all of which have binary values of yes/no
checkboxGroupInput(inputId = "RE_check",
label = h3("Recycleables"),
choices = list("Glass" = RE$GL, "Aluminum" = RE$AL, "Plastic" = RE$PL),
selected = 0)
),
dashboardBody(
fluidRow(box(width = 12, leafletOutput(outputId = "map"))),
tags$style(type = "text/css", "#map {height: calc(100vh - 80px) !important;}"),
leafletOutput("map")
)
)
And now for the trouble I'm having: What do I put into my server so it observes each of these events?
This is what I have for the event in which a user checks "glass", and I have no idea how wrong or how right it is. I just know it's not working. I'm trying to use "if" statements, so only values that equal "yes" populate the map. But currently, the map in the dashboard is blank no matter what I do, although the checkbox group input seems to work.
server <- function(session, input, output) {
observeEvent({
RE_click <- input$map_marker_click
if (is.null(RE_click))
return()
if(input$RE$GL == "Yes"){
leafletProxy("map") %>%
clearMarkers() %>%
addMarkers(data = RE_click,
lat = RE$y,
lng = RE$x)
return("map")
}
})
Here's my output leaflet map too, in case that matters:
output$map <- renderLeaflet({
leaflet() %>%
setView(lng = -83.5, lat = 37.6, zoom = 8.5) %>%
addProviderTiles("Esri.WorldImagery") %>%
addProviderTiles(providers$Stamen.Toner, group = "Toner") %>%
addPolygons(data = counties,
color = "green",
weight = 1,
fillOpacity = .1,
highlight = highlightOptions(
weight = 3,
color = "green",
fillOpacity = .3)) %>%
addMarkers(data = RE,
lng = ~x, lat = ~y,
label = lapply(RE$popup, HTML),
group = "recycle",
clusterOptions = markerClusterOptions(showCoverageOnHover = FALSE)) %>%
addLayersControl(baseGroups = c("Esri.WorldImagery", "Toner"),
overlayGroups = c("recycle"),
options = layersControlOptions(collapsed = FALSE))
})
}
I'm new to R Shiny if that's not obvious. I'd really appreciate any and all help.
All my code is publicly available on my GitHub for download:
https://github.com/mallen011/Leaflet_and_Shiny
Thanks and stay safe!
Maybe this would work... You can add the different recycle types as layers, then add the checkboxes on the leaflet map instead of worrying about shiny integration. Obviously, you'd have to add the rest of your recycle types on here...
library(leaflet)
library(htmlTable)
RE <- read.csv("https://raw.githubusercontent.com/mallen011/Leaflet_and_Shiny/master/Shiny%20Leaflet%20Map/csv/RE.csv")
leaflet() %>%
setView(lng = -83.5, lat = 37.6, zoom = 8.5) %>%
addProviderTiles("Esri.WorldImagery") %>%
addProviderTiles(providers$Stamen.Toner, group = "Toner") %>%
# addPolygons(data = counties,
# color = "green",
# weight = 1,
# fillOpacity = .1,
# highlight = highlightOptions(
# weight = 3,
# color = "green",
# fillOpacity = .3)) %>%
addMarkers(data = RE[RE$AL=="Yes", ],
lng = ~x, lat = ~y,
#label = lapply(RE$popup, HTML),
group = "AL",
clusterOptions = markerClusterOptions(showCoverageOnHover = FALSE)) %>%
addMarkers(data = RE[RE$FE=="Yes", ],
lng = ~x, lat = ~y,
#label = lapply(RE$popup, HTML),
group = "FE",
clusterOptions = markerClusterOptions(showCoverageOnHover = FALSE)) %>%
addMarkers(data = RE[RE$NONFE=="Yes", ],
lng = ~x, lat = ~y,
#label = lapply(RE$popup, HTML),
group = "NONFE",
clusterOptions = markerClusterOptions(showCoverageOnHover = FALSE)) %>%
addLayersControl(baseGroups = c("Esri.WorldImagery", "Toner"),
overlayGroups = c("AL", "FE", "NONFE"),
options = layersControlOptions(collapsed = FALSE))
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")
)
AIM
Create a leaflet map using Shiny that represents one set of data with circle marker and add a markers for points using a second set of data.
ISSUE
The "circle" markers are working, but "markers" are not. The "addMarkers" code is not being read or is being ignored.
SERVER
library(shiny)
library(leaflet)
server <- function(input, output, session) {
points <- read.csv(textConnection("Loc,STZip,Lat,Long,Vol
Loc1,17699,40.0185,-76.297582,15
Loc2,76177,32.949819,-97.31406,20
Loc3,27801,35.935125,-77.77076,17
Loc4,52404,41.947335,-91.68819,12
Loc5,19380,39.983108,-75.59332,18
"))
newpoints <- read.csv(textConnection("Loc,STZip,Lat,Long,Vol
Loc6,18640,41.317242,-75.77942,12
Loc7,38133,35.208709,-89.80518,20
"))
output$mymap <- renderLeaflet({
leaflet() %>%
addProviderTiles("Stamen.TonerLite",
options = providerTileOptions(noWrap = TRUE)) %>%
addCircleMarkers(lng = ~Long, lat = ~Lat, radius = ~Vol, layerId = NULL,
group = "NGS_Facilities", stroke = TRUE, color = "#0000CC", weight = 5, opacity = 0.5,
fill = TRUE, fillColor = "#0000CC", fillOpacity = 0.2, dashArray = NULL,
popup = ~Loc, options = pathOptions(), clusterOptions = NULL, clusterId = NULL,
data = (newpoints)) %>%
#this code is not being read or is ignored...
addMarkers(lng = ~Long, lat = ~Lat, popup = ~Loc, data = (newpoints))
})
}
UI
library(shiny)
library(leaflet)
r_colors <- rgb(t(col2rgb(colors()) / 255))
names(r_colors) <- colors()
ui <- fluidPage(
title = "Map of Stuff",
leafletOutput("mymap", width = 1800, height = 800),
p()
)
This is a weird error... fought with it for a while, until I realized it was a problem with how you read your data.
> newpoints
Loc STZip Lat Long Vol
1 Loc6 18640 41.31724 -75.77942 12
2 Loc7 38133 35.20871 -89.80518 20
3 NA NA NA NA
Because your end quote is on a new line, it leaves a break. This causes the last line in your data to be NAs. When I was debugging, it seemed like anything I put before the data would display, but after would fail.
To fix this, read your data as:
points <- read.csv(textConnection("Loc,STZip,Lat,Long,Vol
Loc1,17699,40.0185,-76.297582,15
Loc2,76177,32.949819,-97.31406,20
Loc3,27801,35.935125,-77.77076,17
Loc4,52404,41.947335,-91.68819,12
Loc5,19380,39.983108,-75.59332,18"))
newpoints <- read.csv(textConnection("Loc,STZip,Lat,Long,Vol
Loc6,18640,40.0185,-76.297582,12
Loc7,38133,35.208709,-89.80518,20"))
For whatever reason, Leaflet bugs out if the last row is all NAs