I am trying to use the slider function to select polygons using Shiny on a Leaflet map.
The following question points me in the right direction, but I can't see how the sliderInput is calling the correct polygons. There is something I am missing.
Dynamically render choropleth map with sliderInput in R shiny
Data is wave-shp (wave.shp) on the following page: https://www.renewables-atlas.info/downloads/. Transformed into geoJSON using QGIS. This is transformed by just exporting to geoJSON, a two minute conversion.
I suspect I need to filter somewhere, but not sure if this should be in ui or server, and not sure how to relate the filter to slider function.
Here is my code:
library(shiny)
library(leaflet)
library(rgdal)
library(sf)
library(dplyr)
library(RColorBrewer)
wave_data <- read_sf("Wave_data_32631.geojson")
wave_data <- st_transform(wave_data, crs = '+proj=longlat
+datum=WGS84')
# For linked shapefile:
# wave_data <- read_sf("~/path/Wave.shp")
# wave_data <- st_transform(wave_data, crs = '+proj=longlat
# +datum=WGS84')
## Load map
wave_data_map <- leaflet() %>%
addProviderTiles(providers$Esri.WorldTopoMap) %>%
setView(lng = -4.2026458, lat = 56.4906712, zoom = 5)
wave_data_map
bins <- c(0, 25, 50, 100, 150, 200, 300, 400, 500, 1000, 3100)
pal <- colorBin("RdYlBu", domain = wave_data$Ave_Depth, bins =
bins)
## Add polygons
wave_data_map <- leaflet() %>%
addProviderTiles(providers$Esri.WorldTopoMap) %>%
setView(lng = -4.2026458, lat = 56.4906712, zoom = 5) %>%
addPolygons(data = wave_data,
weight = 1,
smoothFactor = 0.5,
color = "white",
fillOpacity = 0.5,
fillColor = pal(wave_data$Ave_Depth),
)
wave_data_map
## Add legend
wave_data_map <- leaflet() %>%
addProviderTiles(providers$Esri.WorldTopoMap) %>%
setView(lng = -4.2026458, lat = 56.4906712, zoom = 5) %>%
addPolygons(data = wave_data,
weight = 1,
smoothFactor = 0.5,
color = "white",
fillOpacity = 0.3,
fillColor = pal(wave_data$Ave_Depth)) %>%
addLegend(pal = pal,
values = wave_data$Ave_Depth,
title = "Average depth",
labFormat = labelFormat (suffix = "m"),
opacity = 0.7,
position = "bottomright")
wave_data_map
# Define UI for application
ui <- bootstrapPage(
tags$style(type = "text/css", "html, body
{width:100%;height:100%}"),
leafletOutput("wave_data_map", width = "100%", height =
"100%"),
sliderInput("wave_data_range", "Wave energy",
min = 0, max = 75,
value = c(min(wave_data$An_mn_P_OD),
max(wave_data$An_mn_P_OD)),
step = 5,
round = 0.5,
dragRange = TRUE)
))
# Define server logic
server <- function(input, output, session) {
data_input <- reactive ({
wave_data %>%
filter(An_mn_P_OD >= input$wave_data_range[1]) %>%
filter(An_mn_P_OD <= input$wave_data_range[2])
})
output$wave_data_map <- renderLeaflet(
leaflet() %>%
addProviderTiles(providers$Esri.WorldTopoMap) %>%
setView(lng = -4.2026458, lat = 56.4906712, zoom = 5) %>%
addPolygons(data = wave_data,
weight = 1,
smoothFactor = 0.5,
color = "white",
fillOpacity = 0.3,
fillColor = pal(wave_data$Ave_Depth)) %>%
addLegend(pal = pal,
values = wave_data$Ave_Depth,
title = "Average depth",
labFormat = labelFormat (suffix = "m"),
opacity = 0.7,
position = "bottomright")
)
}
# Run the application
shinyApp(ui = ui, server = server)
I have tried 'observe' and 'observeEvent', but I am unfamiliar with these. ? observeEvent() returns that bindEvent() should now be used, but again unfamiliar.
I can send geoJSON if requested, I can't see how to attach to this post.
Many thanks in advance.
I tried to publish an R Shiny app but I got this error 1
I don't know what to do
ps: I have updated all the libraries that I use inside the code but still nothing I get the same error
would you please help me!
I am using the following code:
library(shiny)
library(dplyr)
library(rgdal)
library(leaflet)
library(shinyWidgets)
library(shinydashboard)
basin <- readOGR("data/basin.kml", "basin")
map_allocator1 <- read.csv('data/map_allocator1.csv')
map_allocator2 <- read.csv('data/map_allocator2.csv')
map_allocator3 <- read.csv('data/map_allocator3.csv')
tour_polyline <- readOGR("data/tour1.kml", "tour1")
info_360<- read.csv('data/360_photos.csv')
ui <-
fluidPage(theme = "mystyle.css",
sidebarLayout(
sidebarPanel(
tags$head(
tags$style(HTML(".main-sidebar {background-color: #D6E3F0!important;}")))
,
sliderTextInput(
inputId = "mySliderText",
label = "Story line",
grid = TRUE,
force_edges = TRUE,
choices = c('1','2','3','4','5','6')
)
,br(),br()
,
(leafletOutput("story_map")),
htmlOutput("frame2")
),
mainPanel(
tags$head(tags$style("#current_info{
margin-left:20px;
margin-right:10px;
}"
)
)
,
valueBoxOutput("story_line_valubox"),
htmlOutput("frame")
,
div(id='box1', "Infromation about the current location")
,
htmlOutput("frame1")
#uiOutput("current_info")
)
)
)
server <- function(input, output) {
printmap <- reactive({
if (input$mySliderText %in% info_360$press )
{
info_360 %>%
filter(press == input$mySliderText)
}
})
printingvaluebox <- reactive({
if (input$mySliderText %in% info_360$press )
{
info_360 %>%
filter(press == input$mySliderText) %>%
pull(valuebox)
}
})
output$story_map<- renderLeaflet({
leaflet() %>%
addProviderTiles("Stamen.Watercolor",options = providerTileOptions(minZoom=6, maxZoom=6)) %>%
addPolygons(data = basin,color = "black",weight = 2,opacity = 1,fillOpacity = 0.05 )%>%
addCircleMarkers(data = map_allocator1,
lat = ~lat, lng = ~lon,
label = ~no,
radius = 8, fillOpacity = 3/4, stroke = FALSE, color = 'steelblue',
labelOptions = labelOptions(noHide = TRUE, offset=c(0,0), textOnly = TRUE)
)%>%
addCircleMarkers(data = map_allocator2,
lat = ~lat, lng = ~lon,
label = ~no,
radius = 8, fillOpacity = 3/4, stroke = FALSE, color = 'red',
labelOptions = labelOptions(noHide = TRUE, offset=c(0,0), textOnly = TRUE)
)%>%
addCircleMarkers(data = map_allocator3,
lat = ~lat, lng = ~lon,
label = ~no,
radius = 8, fillOpacity = 3/4, stroke = FALSE, color = 'yellow',
labelOptions = labelOptions(noHide = TRUE, offset=c(0,0), textOnly = TRUE)
)%>%
addPolylines(data=tour_polyline, color = "red",weight = 1,opacity = 1)%>%
addMarkers(data=printmap())
})
output$story_line_valubox <- renderValueBox({
valueBox(
printingvaluebox(),
width = 7,
"Current Excursion Station",
color = "blue"
)
})
output$story_line_map<- renderLeaflet({
leaflet() %>%
addProviderTiles("Esri.WorldImagery",options = tileOptions(minZoom = 3 , maxZoom = 16)) %>%
setView(lng=printmap()$lon, lat=printmap()$lat, zoom=printmap()$zoom_level)
})
selectHtml <- reactive({
if (input$mySliderText ==1)
{
return(("trial1.html"))
}
else
{
return(("triaL2.html"))
}
})
frame_link<- reactive({
if (input$mySliderText %in% info_360$press )
{
info_360 %>%
filter(press == input$mySliderText) %>%
pull(mapox)
}
})
output$frame <- renderUI({
tags$iframe(src=frame_link(), height=700, width=1000)
})
output$frame1 <- renderUI({
tags$iframe(src=selectHtml(), height=700, width=1000)
})
output$frame2 <- renderUI({
tags$iframe(src='carousel.html', height=390, width=575, style="position:relative; top: 20px; left: 0px;")
})
}
# Run the application
shinyApp(ui = ui, server = server)
I have published 3 apps in R Shiny and all of them were successfully completed, this time I don't know what is the exact problem!
I would like to load data and set up a custom projection in R Shiny. I am able to load the data but cannot get the projection right (ESPG:26916). I have searched but am not sure what I have missed. Help much appreciated.
Here is the code I have
library(leaflet)
library(tidyverse)
ui <- fluidPage(
column(
width = 4,
leafletOutput("mymap", width = 1400, heigh = 700)),
p(),
fileInput("in_file", "Input file:",
accept=c("txt/csv", "text/comma-separated-values,text/plain", ".csv", "Decimal seperator")),
actionButton("upload_data", "Visualize New points")#,
)
server <- function(input, output, session) {
visualize <- reactive({
if(input$upload_data==0) {
return(NULL)
}
df <- read.csv(input$in_file$datapath,
sep = ',',
header = TRUE,
quote = "#",
row.names = NULL)
epsg26916 <- leafletCRS(
crsClass = "L.Proj.CRS",
code = 'EPSG:26916',
proj4def = "+proj=utm +zone=16 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs",
resolutions = 2^(15:-1)
)
return(leaflet(df,
options = leafletOptions(crs = epsg26916)
) %>%
addProviderTiles(providers$Esri.WorldImagery,
options = providerTileOptions(noWrap = TRUE)) %>%
setView(-85.39310209, 42.41438242, zoom = 16) %>%
addCircleMarkers(~easting, ~northing,
group = "my data",
weight = 1, fillOpacity = 0.7, radius = 3) %>%
addLayersControl(overlayGroups = c("my data"))
)
})
output$mymap <- renderLeaflet({
visualize()
})
}
shinyApp(ui, server)
I have seen that this problem has happened to other people, but their solutions have not worked for me. I have my app.R file and a .RData file with the required inputs in the same ECWA_Strategic_Planning_Tool directory. When I run:
library(rsconnect)
rsconnect::deployApp('C:/Users/mikialynn/Documents/Duke/Spring2017/MP/GISTool/Final/ECWA_Strategic_Planning_Tool')
I get the following error on the web page that opens up:
ERROR: An error has occurred. Check your logs or contact the app author for clarification.
However, I cannot find anything wrong. I install all of my packages, I use relative pathways etc. I am pasting all of the code from my app below. If anyone can spot what I'm doing wrong, I would greatly appreciate it!
library(shiny)
library(leaflet)
library(sp)
library(rgdal)
library(rstudioapi) # For working directory
library(raster)
library(RColorBrewer)
library(rgeos) #Maybe use gSimplify to simplify polygon
library(DT) #To make interactive DataTable
library(plotly) #For pie chart
library(ggplot2) # for layout
# Set Working Directory
setwd(dirname(rstudioapi::getActiveDocumentContext()$path))
# Load R Workspace
load('Shiny.Strategies.RData')
# UI variables
neigh.names <- levels(merge.proj$View)
neigh.default <- c("Urban7")
dt.names <- c('PARCEL_ID', 'PIN', 'OWNER_NAME', 'SITE_ADDRE', 'OWNER_ADDR',
'SUM_ACRE', 'LANDUSE_DE', 'LAND_VALUE', 'TOTAL_VALU', 'SALE_PRICE',
'Pluvial_WtScore', 'Rest_WtScore', 'GI_WtScore', 'SC_WtScore',
'UNCWI_WtScore', 'Total_Score', 'View')
dt.default <- c('PARCEL_ID', 'Pluvial_WtScore', 'Rest_WtScore',
'GI_WtScore', 'SC_WtScore', 'UNCWI_WtScore', 'Total_Score', 'View')
# Build UI
ui <- fluidPage(
titlePanel("ECWA Strategic Planning Tool"),
HTML('<br>'),
column(2,
HTML("<strong>Instructions:</strong><br/><br/>"),
HTML("<p>1) Select weights for parameters and click 'Run' to
initiate tool.<br/><br/>
2) Use rightside panel to adjust Table and Map Settings.<br/>
<br/>
3) Use search/sort functions of Table to identify parcels.
Select row to display Total Score Chart.<br/><br/>
4) Input View and Parcel ID from Table to Map settings to
identify parcel in Map.<br/><br/>
5) When satisfied with weights, click 'Export Shapefile' to
save shapefile of all parcels.<p/><br/>"),
HTML("<strong>Calculate Parcel Scores: </strong><br/>"),
helpText('The sum of the weights must equal to 1.'),
sliderInput(inputId = "weightPluvial", label = "Weight for Pluvial
Flooding",
value = 0.20, min = 0, max = 1),
sliderInput(inputId = "weightRest", label = "Weight for
Restoration",
value = 0.20, min = 0, max = 1),
sliderInput(inputId = "weightGI", label = "Weight for Green
Infrastructure",
value = 0.20, min = 0, max = 1),
sliderInput(inputId = "weightSC", label = "Weight for City
Stormwater Controls",
value = 0.20, min = 0, max = 1),
sliderInput(inputId = "weightUNCWI", label = "Weight for UNCWI",
value = 0.20, min = 0, max = 1),
actionButton("run", "Run"),
actionButton("export", "Export Shapefile")),
column(8,
HTML("<h3><strong>Table Summary</strong></h3>"),
HTML("<br>"),
dataTableOutput("table")),
column(2,
HTML("<p><br><br></p>"),
HTML("<h4>Table Settings:</h4>"),
checkboxGroupInput(inputId = 'show_vars', label = 'Select column(s)
to display in Table:', choices = dt.names, selected = dt.default),
HTML("<strong>Total Score Chart:</strong>"),
helpText("Please select Table row to display pie chart."),
plotlyOutput("pie")
),
fluidRow(
column(8, offset = 2,
HTML("<br>"),
HTML("<h3><strong>Map Display</strong></h3>"),
leafletOutput("map", height = 800),
HTML("<br><br>")),
column(2,
HTML("<p><br><br><br></p>"),
HTML("<h4>Map Settings:</h4>"),
checkboxGroupInput(inputId = 'show_neigh', label = 'Select
View(s) to display in Map:', choices = neigh.names,
selected = neigh.default),
HTML("<br>"),
sliderInput("range", "Select score range to display in Map:", min
= 0.0, max= 10.0, value = as.numeric(c("0.0", "10.0")), step = 0.1),
HTML("<br>"),
HTML("<strong>Parcel Zoom:</strong>"),
helpText("The View and Score Range must contain the parcel of
interest to execute zoom."),
numericInput('parcel','Enter Parcel ID',0)
)
))
# SERVER
server <- function(input, output) {
defaultData <-
eventReactive(input$run, {
# Multiply by Weights
merge.proj#data$Pluvial_WtScore <-
round(merge.proj#data$Pluvial_Score*input$weightPluvial, digits = 1)
merge.proj#data$Rest_WtScore <-
round(merge.proj#data$Rest_Score*input$weightRest, digits = 1)
merge.proj#data$GI_WtScore <-
round(merge.proj#data$GI_Score*input$weightGI, digits = 1)
merge.proj#data$SC_WtScore <-
round(merge.proj#data$SC_Score*input$weightSC, digits = 1)
merge.proj#data$UNCWI_WtScore <-
round(merge.proj#data$UNCWI_Score*input$weightUNCWI, digits = 1)
# Find Total Score
merge.proj#data$Total_Score <- merge.proj#data$Pluvial_WtScore +
merge.proj#data$Rest_WtScore + merge.proj#data$GI_WtScore +
merge.proj#data$SC_WtScore + merge.proj#data$UNCWI_WtScore
return(merge.proj)
})
# Subset by neighborhood
neighData <- reactive ({
merge.proj <- defaultData()
merge.proj[merge.proj$View%in%input$show_neigh,]
})
# Plot with leaflet
# Palette for map
colorpal <- reactive({
merge.proj <- neighData()
colorNumeric(palette = "YlOrRd",
domain = merge.proj$Total_Score)
})
# Pop Up Option for map
# popup <- paste0("<strong>Parcel ID: </strong>",
# merge.proj#data$PARCEL_ID,
# "<br><strong>Total Score: </strong>",
# merge.proj#data$Total_Score)
# Label Option for map
labels <- reactive({
merge.proj <- neighData()
sprintf("<strong>Parcel ID: </strong>%s<br/><strong>Total Score:
</strong>%g",
merge.proj$PARCEL_ID,
merge.proj$Total_Score) %>% lapply(htmltools::HTML)
})
# Render Default Map
output$map <- renderLeaflet ({
merge.proj <- neighData()
pal <- colorpal()
lab <- labels()
leaflet() %>%
#addProviderTiles(provider='Esri.WorldImagery') %>%
# setView(zoom =) %>%
addTiles() %>%
addPolygons(
#data = merge.proj[input$show_neigh,, drop = FALSE],
data=merge.proj,
fillColor = ~pal(Total_Score),
weight = 1,
opacity = 1,
color = "white",
dashArray = "3",
fillOpacity = 0.7,
highlight = highlightOptions(
weight = 3,
color = "#666",
dashArray = "",
fillOpacity = 0.7,
bringToFront = TRUE),
# popup= popup) %>%
label = lab,
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px"),
textsize = "15px",
direction = "auto")) %>%
addLegend(position = "bottomleft",pal = pal, opacity = 0.7, values =
merge.proj$Total_Score, title = "<strong>Total Score</strong>")
})
# Build Data Table
output$table <- renderDataTable({
merge.proj <- defaultData()
table.dat <- merge.proj[, c('PARCEL_ID', 'PIN', 'OWNER_NAME',
'SITE_ADDRE', 'OWNER_ADDR', 'SUM_ACRE', 'LANDUSE_DE', 'LAND_VALUE',
'TOTAL_VALU', 'SALE_PRICE', 'Pluvial_WtScore', 'Rest_WtScore', 'GI_WtScore',
'SC_WtScore', 'UNCWI_WtScore', 'Total_Score', 'View')]
datatable(data = table.dat#data[, input$show_vars, drop = FALSE],
options = list(lengthMenu = c(5, 10, 20, 30), pageLength = 20), rownames =
FALSE)
})
# Plot-ly
output$pie <- renderPlotly({
merge.proj <- defaultData()
names <- c('Pluvial', 'Rest', 'GI', 'SC', 'UNCWI')
colors <- c('rgb(128,133,133)', 'rgb(211,94,96)', 'rgb(144,103,167)',
'rgb(114,147,203)', 'rgb(171,104,87)')
selectedrowindex <-
input$table_rows_selected[length(input$table_rows_selected)]
selectedrowindex <- as.numeric(selectedrowindex)
df <- data.frame(merge.proj[selectedrowindex, c('Pluvial_WtScore',
'Rest_WtScore', 'GI_WtScore', 'SC_WtScore', 'UNCWI_WtScore')])
vector <- unname(unlist(df[1,]))
if (!is.null(input$table_rows_selected)) {
par(mar = c(4, 4, 1, .1))
plot_ly(labels = names, values = vector, type = 'pie',
textposition = 'inside',
textinfo = 'label+percent',
insidetextfont = list(color = '#FFFFFF'),
hoverinfo = 'text',
text = ~paste('Score:', vector),
marker = list(colors = colors,
line = list(color = '#FFFFFF', width = 1)),
#The 'pull' attribute can also be used to create space between the sectors
showlegend = FALSE) %>%
layout(#title = '% Total Score',
xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE))
}
else {return(NULL)}
})
# Update map to parcel score slider
# Subset data
filteredData <- reactive({
merge.proj <- neighData()
merge.proj[merge.proj#data$Total_Score >= input$range[1] &
merge.proj#data$Total_Score <= input$range[2],]
})
# New Palette
colorpal2 <- reactive({
merge.proj <- filteredData()
colorNumeric(palette = "YlOrRd",
domain = merge.proj$Total_Score)
})
# Pop Up Option
# popup <- paste0("<strong>Parcel ID: </strong>",
# merge.proj#data$PARCEL_ID,
# "<br><strong>Total Score: </strong>",
# merge.proj#data$Total_Score)
# Label Option
labels2 <- reactive({
merge.proj <- filteredData()
sprintf("<strong>Parcel ID: </strong>%s<br/><strong>Total Score:
</strong>%g",
merge.proj$PARCEL_ID,
merge.proj$Total_Score) %>% lapply(htmltools::HTML)
})
#Leaflet Proxy
observe({
merge.proj <- filteredData()
pal2 <- colorpal2()
lab2 <- labels2()
leaf <- leafletProxy("map", data = filteredData()) %>%
clearShapes() %>%
addPolygons(
fillColor = ~pal2(Total_Score),
weight = 1,
opacity = 1,
color = "white",
dashArray = "3",
fillOpacity = 0.7,
highlight = highlightOptions(
weight = 3,
color = "#666",
dashArray = "",
fillOpacity = 0.7,
bringToFront = TRUE),
# popup= popup) %>%
label = lab2,
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px"),
textsize = "15px",
direction = "auto"))
if(input$parcel>0){
sub.dat <- merge.proj[merge.proj$PARCEL_ID==input$parcel,]
zx <- mean(extent(sub.dat)[1:2])
zy <- mean(extent(sub.dat)[3:4])
leaf <- leaf %>%
setView(lng=zx,lat=zy,zoom=16)
}
leaf
})
#Update Legend
observe({
proxy <- leafletProxy("map", data = filteredData())
pal2 <- colorpal2()
proxy %>% clearControls()
proxy %>% addLegend(position = "bottomleft",pal = pal2, opacity = 0.7,
values = ~Total_Score, title = "<strong>Total Score</strong>")
})
# Export new shapefile
#make so that user can choose name and allow overwrite
observeEvent(input$export, {
merge.proj <- defaultData()
writeOGR(merge.proj, dsn = "Data", layer = "Strategies_Output", driver =
"ESRI Shapefile")
})
}
shinyApp(ui = ui, server = server)
Issue resolved! My initial suspicion was correct; it had to do with the .rdata file. It also relates to shinyapp.io's servers which run on a Linux based server. From my reading, Linux only handles lowercase file paths and extensions. The reason why it worked for the .csv file is because it's pretty common to have the file extension saved in all lowercase. This was not the case for the .RData file. Using the RStudio IDE and the physical "Save Workspace" button, the default file extension is .RData (case sensitive). I couldn't rename the file extension (for some reason, I'm not the most tech-savvy person). Similar to the load() function, there's the save() function. Previously, I used the save() file as follows (note the capitalized .RData at the end):
save(df_training_separated_with_models, file = "sample_data_with_models.RData")
However, using the same function in all lowercase fixes the issue:
save(df_training_separated_with_models, file = "sample_data_with_models.rdata")
Hope this helps any other poor soul with the same issue that is scouring the internet and other forums.
Cheers!