R Shiny App working locally but not on shinyapps.io - shiny

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!

Related

Dynamically render choropleth map with sliderInput in R shiny 2

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.

How to create a numericinput widget in Shiny app to add new observations to existing data frame?

sorry if this is repetitive and so simple it is annoying, but I am new to Shiny.
I need help with a shiny app I am trying to create for my golf game. I have loaded a CSV file with previous distance and accuracy observations to Rstudio and completed a script file with what will generally be done: data preprocessing and then visualizations.
I am now struggling with converting that to the app.R file, specifically, how to create a widget where I can add new numeric observations to the current data frame. The end goal is to use the app to log data as I play (practice or an actual round), which updates in real time for quick insight into the average distance and accuracy for each club.
Here is the very basic shiny code I have got to work for the numeric input:
`library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
titlePanel("Numeric Add Test"),
column(3,
numericInput("num",
h3("Numeric input"),
value = 1,
min = 50,
max = 400,
step = 25))
)
# Define server logic required to draw a histogram
server <- function(input, output) {
}
# Run the application
shinyApp(ui = ui, server = server)`
I have found ways to include an 'add' button to a list, but what I am hoping to do is have the new numeric input be added to the specified variable (club, distance, accuracy) in the referenced dataset. This action would change the existing data, but add to it and grow the dataset over time.
Not sure if this helps for context at all, but below is the script file for preprocessing and visuals I described above:
`######### Golf Data Practice for App #############
## Read in Data set and address the column names starting with a number
Golfdata <- data.frame(read_csv("Shiny Apps/Golf Dataset .csv"))
Golfdata <- as.data.frame(Golfdata)
#Drop the last two columns for only clubs. Then create shot bias DF as well.
Clubs <- Golfdata %>% select(-c(11,12))
ShotBias <- Golfdata %>% select(c(11,12))
#Visualize the Average club distance
##Convert the club df by summarizing each variable by its average,
## then use the gather() to convert to long instead of wide to finally
## prepare the df for visualizing.
ClubAverage <- Clubs %>% summarise_all(mean) %>% gather(ClubAverage) %>%
mutate_if(is.numeric, round, digits = 0)
library(ggplot2)
value <- ClubAverage$value
ggplot(ClubAverage) +
aes(x = fct_reorder(ClubAverage, value, .desc = TRUE), y = value, label = value,
color = ClubAverage) +
geom_col( show.legend = FALSE, fill = "white") +
geom_text(nudge_y = 10, color = "black", size=4, fontface = "bold") +
labs(x = "Club",
y = "Yards", title = "Average Club Distance") +
theme(panel.background = element_rect(fill="forestgreen"),
panel.grid.major.x = element_blank(),
panel.grid.major = element_line(color = "yellow"),
panel.grid.minor = element_line(color = "yellow1")) +
theme(plot.title = element_text(size = 24L,
face = "bold", hjust = 0.5), axis.title.y = element_text(size = 18L, face = "bold"), axis.title.x =
element_text(size = 18L,
face = "bold"))
## Visualize the Average Accuracy ##
## This time, summarize the columns by their mean,
## but keep as wide -- no gather() function needed.
AverageShotBias <- ShotBias %>% summarise_all(mean)
ggplot(AverageShotBias) +
aes(x = Accuracy.Bias, y = Distance.Bias) +
geom_point(shape = "circle filled",
size = 18L, fill = "yellow") +
labs(x = "Accuracy", y = "Distance", title = "Average Shot Bias") +
theme(panel.background = element_rect(fill="forestgreen")) +
theme(plot.title = element_text(size = 24L, face = "bold", hjust = 0.5), axis.title.y =
element_text(size = 14L,
face = "bold"), axis.title.x = element_text(size = 14L, face = "bold")) +
xlim(-1, 1) +
ylim(-1, 1) +
geom_hline(yintercept = 0, size=1) +
geom_vline(xintercept = 0, size=1)`
Something I have found regarding the add button is the code here:
` ,actionButton('add','add')
,verbatimTextOutput('list')
)`
This does create an add button, which after updating the server code does create a list of added inputs, however I would like to be able to adjust the code for adding the observation to the variables in the data set.
I assume I would create an add button for each variable, just need to understand better how to do that.
The structure of your data used in the plot is not clear, but this is how to get the inputs or update dataset using eventReactive or observeEvent in the server. you can read this to learn the difference
server <- function(input, output) {
distance <- eventReactive(input$addButton, {
input$distInput
}, ignoreInit = T, ignoreNULL = F)
accbias <- eventReactive(input$accBiasButton, {
input$accslider
})
distbias <- eventReactive(input$DistBiasButton, {
input$distslider
}, ignoreNULL=F)
output$plot1 <- renderPlot({
input$distInput
mydist <- distance()
# plot
})
output$plot2 <- renderPlot({
input$distInput # use the inputs here
mydist <- distance() # or the reactives
})
}
the two output plots in your code have the same outputId
Follow UP to my Question: I have written the code for the ui, now I am still trying to figure out how to code the server properly so the distance and accuracy numeric inputs can be added to a data frame. That data frame will then be used to create the two visuals.
library(shiny)
library(gridlayout)
library(DT)
library(tidyverse)
ui <- grid_page(
layout = c(
"title title title",
"h1 h2 h3 ",
"h4 h4 h5 "
),
row_sizes = c(
"100px",
"0.86fr",
"1.14fr"
),
col_sizes = c(
"250px",
"0.71fr",
"1.29fr"
),
gap_size = "1rem",
grid_card_text(
area = "title",
content = "My Golf Data",
alignment = "center",
is_title = FALSE
),
grid_card(
area = "h2",
title = "Distance Input",
numericInput(
inputId = "distInput",
label = "Distance",
value = 50L,
min = 50L,
max = 400L,
step = 15L
),
actionButton(
inputId = "addButton",
label = "Add",
width = "100%"
)
),
grid_card(
area = "h1",
title = "Club Select",
radioButtons(
inputId = "clubRadiobuttons",
label = "",
choices = list(
Driver = "D",
`5Wood` = "5W",
`4H` = "4H",
`5I` = "5I",
`6I` = "6I",
`7I` = "7I",
`8I` = "8I",
`9I` = "9I",
PW = "PW",
SW = "SW"
),
width = "100%"
)
),
grid_card(
area = "h3",
title = "Accuracy",
sliderInput(
inputId = "accslider",
label = "Accuracy Bias",
min = -1L,
max = 1L,
value = 0L,
width = "98%",
step = 1L
),
actionButton(
inputId = "accBiasButton",
label = "Add Acc Bias",
width = "100%"
),
sliderInput(
inputId = "distslider",
label = "Distance Bias",
min = -1L,
max = 1L,
value = 0L,
width = "100%",
step = 1L
),
actionButton(
inputId = "DistBiasButton",
label = "Add Dist Bias",
width = "100%"
)
),
grid_card(
area = "h5",
title = "Average Club Distance",
plotOutput(
outputId = "plot",
width = "100%",
height = "400px"
)
),
grid_card(
area = "h4",
title = "Accuracy Average",
plotOutput(
outputId = "plot",
width = "100%",
height = "400px"
)
)
)
server <- function(input, output) {
}
shinyApp(ui, server)

Rmarkdown - interactive model

Whoever come across with JMP agrees that its model profiler is the best thing you can find on that software.
Simply is a series of interactive plots of the model (I don't think there is a better way to communicate an additive model - looks like the one below)
Now, I would like to have something similar in my html rmarkdown reports.
It seems that might be possible to add rshiny on rmarkdows so I've managed to get something like the below on RShiny.
library(tidyverse)
library(shiny)
inputData <- mtcars
lm1 <- lm(mpg ~ hp + I(hp^2) + wt * cyl, data = mtcars)
ui <- fluidPage(
titlePanel("Profiler"),
sidebarLayout(
sidebarPanel(
helpText("Choose the level of each factor"),
sliderInput("var_1", label= paste(names(inputData)[2]),
min = min(inputData[,2]),
max = max(inputData[,2]),
value = mean(inputData[,2]),
step = diff(range(inputData[,2]))/50),
sliderInput("var_2", paste(names(inputData)[6]),
min = min(inputData[,6]),
max = max(inputData[,6]),
value = mean(inputData[,6]),
step = diff(range(inputData[,6]))/50),
sliderInput("var_3", paste(names(inputData)[4]),
min = min(inputData[,4]),
max = max(inputData[,4]),
value = mean(inputData[,4]),
step = diff(range(inputData[,4]))/50)
),
mainPanel(
tableOutput('table_pred'),
plotOutput("plot2"),
plotOutput("plot3"),
plotOutput("plot1")
)
)
)
server <- function(input, output) {
# Data declaration
data <- reactive({
req(input$var_1, input$var_2,input$var_3)
data.frame(cyl = input$var_1, wt = input$var_2, hp = input$var_3)
})
# The new predicted value for the specific input
pred <- reactive({
predict(lm1, data(), se = T, interval="confidence", level=0.95)$fit %>% as_tibble() %>%
rename(Prediction = fit, `Lower limit` = lwr, `Upper limit` = upr)
})
# Present as table the outcome of specific inputs
output$table_pred <- renderTable({
pred()
})
# Prepare the plots
# Create the continuum space for the predictors
hp_space <- reactive({
seq(min(mtcars$hp), max(mtcars$hp), length.out = 1e3)
})
cyl_space <- reactive({
seq(min(mtcars$cyl), max(mtcars$cyl), length.out = 1e3)
})
wt_space <- reactive({
seq(min(mtcars$wt), max(mtcars$wt), length.out = 1e3)
})
# Perform predictions for each point
new_pred_hp <- reactive({
temp <- tibble(hp = hp_space(), cyl = input$var_1, wt = input$var_2 )
temp %>%
bind_cols(predict(lm1, newdata = temp,
se = T, interval="confidence", level=0.95)$fit %>% as_tibble)%>%
mutate(Predictor = 'hp')
})
new_pred_cyl <- reactive({
temp <- tibble(hp = input$var_3, cyl = cyl_space(), wt = input$var_2 )
temp %>%
bind_cols(predict(lm1, newdata = temp,
se = T, interval="confidence", level=0.95)$fit %>% as_tibble)%>%
mutate(Predictor = 'cyl')
})
new_pred_wt <- reactive({
temp <- tibble(hp = input$var_3, cyl = input$var_1, wt = wt_space())
temp %>%
bind_cols(predict(lm1, newdata = temp,
se = T, interval="confidence", level=0.95)$fit %>% as_tibble) %>%
mutate(Predictor = 'wt')
})
# Make one plot per predictor
output$plot1 <- renderPlot({
ggplot(new_pred_hp(), aes( x = hp, y = fit)) +
geom_ribbon(aes(ymin = lwr, ymax = upr), alpha = 0.1, fill = 'red') +
geom_line(size = 1, color = 'black')+
geom_vline(xintercept = input$var_3, colour = 'red', linetype = 'dashed')
})
output$plot2 <- renderPlot({
ggplot(new_pred_cyl(), aes( x = cyl, y = fit)) +
geom_ribbon(aes(ymin = lwr, ymax = upr), alpha = 0.1, fill = 'red') +
geom_line(size = 1, color = 'black')+
geom_vline(xintercept = input$var_1, colour = 'red', linetype = 'dashed')
})
output$plot3 <- renderPlot({
ggplot(new_pred_wt(), aes( x = wt, y = fit)) +
geom_ribbon(aes(ymin = lwr, ymax = upr), alpha = 0.1, fill = 'red') +
geom_line(size = 1, color = 'black')+
geom_vline(xintercept = input$var_2, colour = 'red', linetype = 'dashed')
})
}
shinyApp(ui, server)
Which looks like that,
Questions:
Is there a more elegant way to get these results on html rmarkdown? (maybe with HTML widgets so as to avoid rshiny?)
How to add all this complicated rshiny code (for my intro level) into rmarkdown report?
Thanks.

Efficient way of showing Datatables in loop

I have a dataset in which there is a variable named "Variables". I want to display tables in shiny app of each unique value of column "Variables". See the snapshot of image below. I am using it via lapply( ). It works fine. But it takes some time to show tables as I have close to 20 tables. Each table has close to 15 columns. Is there any better way to do it in loop other than lapply( ).
stratsgroups <- Detailed %>% distinct(Variables) %>% pull()
observe({
lapply(stratsgroups, function(x) {
output[[paste0('T_', x)]] <- DT::renderDataTable({
# Data Preparation
data() %>% dplyr::filter(Variables == x) %>% select(2:(ncol(Detailed)-2)) %>%
rename(!!x := !!sym("Categories")) %>%
# ==============
# DT Option
# ==============
datatable(rownames=FALSE,
extensions = c('Buttons', 'FixedColumns'), selection = 'none',
options = list(
columnDefs = list(list(className = 'dt-center', targets = '_all')),
paging = T,
pageLength = 10,
searching = FALSE,
ordering=F,
info = F,
dom = 'Bfrtip',
scrollX = TRUE,
fixedColumns = list(leftColumns = 1),
# Callbacks
rowCallback = lastrow(),
fnDrawCallback = DTpagination(),
# Button
buttons = DTmenuitems(Table_Menu, title)
) )
})
})
})
output$dt <- renderUI({
tagList(lapply(stratsgroups, function(i) {
box(dataTableOutput(session$ns(paste0('T_', i))), width = 12)
}))
})

Flexdashboard and absolute panel on a lealfet

Is there a way to include an absolute panel like in this example (https://shiny.rstudio.com/gallery/superzip-example.html) to a flexdashboard (on a leaflet) ?
The idea would be to have a mobile panel dedicated to the leaflet output instead of a sidebar panel.
The absolute panel example here based on a shiny example (with ui and server parts)
library(shiny)
ui <- shinyUI(bootstrapPage(
absolutePanel(
id = "controls", class = "panel panel-default", fixed = TRUE,
draggable = TRUE, top = 60, left = "auto", right = 20, bottom = "auto",
width = 330, height = "auto",
HTML('<button data-toggle="collapse" data-target="#demo">Collapsible</button>'),
tags$div(id = 'demo',
checkboxInput('input_draw_point', 'Draw point', FALSE ),
verbatimTextOutput('summary')))
))
server <- shinyServer(function(input, output, session) {
output$summary <- renderPrint(print(cars))
})
shinyApp(ui = ui, server = server)
a code example below for the Flexdashboard part :
---
title: "Waste Lands - America's forgotten nuclear legacy"
author: Philipp Ottolinger
output:
flexdashboard::flex_dashboard:
theme: journal
social: menu
source_code: embed
---
```{r setup, include = FALSE}
library(flexdashboard)
library(shiny)
library(jsonlite)
library(maptools)
library(ggplot2)
library(tidyr)
library(dplyr)
library(purrr)
library(leaflet)
library(plotly)
sites <- fromJSON(flatten=TRUE,
"https://raw.githubusercontent.com/ottlngr/2016-15/ottlngr/ottlngr/sites.json")
sites$locations <- map(sites$locations, function(x) {
if (nrow(x) == 0) {
data_frame(latitude=NA, longitude=NA, postal_code=NA, name=NA, street_address=NA)
} else {
x
}
})
sites <- unnest(sites)
sites <- sites[complete.cases(sites[,c("longitude", "latitude")]),]
sites$ratingcol <- ifelse(sites$site.rating == 0, "orange",
ifelse(sites$site.rating == 1, "green",
ifelse(sites$site.rating == 2, "red", "black")))
sites$ratingf <- factor(sites$site.rating,
levels=c(3:0),
labels=c("Remote or no potential for radioactive contamination.",
"No authority to clean up or status unclear.",
"Cleanup declared complete.",
"Cleanup in progress."))
sites$campus <- ifelse(grepl("University", sites$site.name) |
grepl("University", pattern = sites$street_address) |
grepl("Campus", sites$street_address), 1, 0)
sites$campuscol <- ifelse(sites$campus == 1, "red", "black")
```
Column {data-width=650}
-----------------------------------------------------------------------
### All sites and their current status
```{r}
leaflet() %>%
addTiles() %>%
fitBounds(-127.44,24.05,-65.30,50.35) %>%
addCircleMarkers(sites$longitude,
sites$latitude,
color = sites$ratingcol,
radius = 6,
fill = T,
fillOpacity = 0.2,
opacity = 0.6,
popup = paste(sites$site.city,
sites$site.name,
sep = "")) %>%
addLegend("bottomleft",
colors = c("orange","green", "red", "black"),
labels = c("Cleanup in progress.",
"Cleanup complete.",
"Status unclear.",
"No potential for radioactive contamination."),
opacity = 0.8)
```
Column {data-width=350}
-----------------------------------------------------------------------
### Number of sites
```{r}
sites %>%
count(ratingf) %>%
plot_ly(type = "bar",
x = ratingf,
y = n,
color = ratingf,
text = paste(n,ratingf,sep=""),
hoverinfo = "text") %>%
layout(xaxis = list(showline = F,
showticklabels = F,
fixedrange = T,
title = ""),
yaxis = list(fixedrange = T,
title = ""))
```
### Sites on campus
```{r}
leaflet() %>%
addTiles() %>%
fitBounds(-127.44,24.05,-65.30,50.35) %>%
addCircleMarkers(sites[sites$campus == 1, ]$longitude,
sites[sites$campus == 1, ]$latitude,
color = sites[sites$campus == 1, ]$campuscol,
radius = 6,
fill = T,
fillOpacity = 0.2,
opacity = 0.6,
popup = paste(sites[sites$campus == 1, ]$site.city,
sites[sites$campus == 1, ]$site.name,
sep = ""))
```
Thanks
Try this.
---
title: "haha"
output:
flexdashboard::flex_dashboard:
orientation: columns
vertical_layout: fill
editor_options:
chunk_output_type: console
runtime: shiny
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(flexdashboard)
library(shiny)
library(leaflet)
```
# without container-fluid
### Sites on campus
```{r}
df <- data.frame(NY = c(-74.418997, 43.257408), CA = c(-120.765285, 35.604380))
renderLeaflet(mapfunction())
```
```{r}
absolutePanel(
draggable = TRUE, top = "15%", left = "auto", right = "5%", bottom = "auto",
width = '30%', height = 'auto',
style = "background: orange; opacity: 0.9",
p(strong("some text")),
selectInput("someinput", label = "location", choices = c("NY", "CA"))
)
```
### server
```{r}
mapfunction <- reactive({
leaflet() %>%
addTiles() %>%
fitBounds(-127.44,24.05,-65.30,50.35) %>%
addMarkers(lng = df[[input$someinput]][1], lat = df[[input$someinput]][2])
})
```
# with container-fluid
```{r}
shinyApp(
fluidPage(
leafletOutput(outputId = "somemap"),
absolutePanel(
draggable = TRUE, top = "15%", left = "auto", right = "5%", bottom = "auto",
width = '30%', height = 'auto', fixed = TRUE,
style = "background: orange; opacity: 0.9",
p(strong("some text")),
selectInput("someinput", label = "location", choices = c("NY", "CA"))
)
),
server = function(input, output, session){
df <- data.frame(NY = c(-74.418997, 43.257408), CA = c(-120.765285, 35.604380))
output$somemap <- renderLeaflet({
leaflet() %>%
addTiles() %>%
fitBounds(-127.44,24.05,-65.30,50.35) %>%
addMarkers(lng = df[[input$someinput]][1], lat = df[[input$someinput]][2])
})
}
)
```
If you need to use interactive components from shiny, like XXinput, you need to specify runtime: shiny on the top, otherwise, you can delete this line.
I use reactive as the simplest server part. If you want to use a more complex server (logic), e.g. several components interact together, you need to write the actual server function. I would suggest just write a shiny app instead of a flexdashboard.
unfortunately, components in flexdash are not inside container-fluid class which with this can allow you to drag the panel. There may be a way to work around, you can search for it. Look at the last chunck, I inserted a actual shiny app and the panel is draggable. You should see two tabs when you run the doc, watch the difference. So, if you really want to drag this panel, you should write a "real" shiny app.