Toggle fill on hover using plotly with Shiny in R - r

I would like to create a plotly plot where the fill under each line is toggled upon mouseover/hover. The closest that I've come is using a combination of plotly and Shiny in the code below. Basically, I use the function event_data("plotly_hover") with a call to add_trace, which generates the fill for the line. However, when the mouse is moved away from the line, or unhovered, I get an error message: Error: incorrect length (0), expecting: 2366. In addition, the hoverinfo text no longer appears, or only briefly before the fill appears.
I'm not sure what the program is looking for when unhovering, so am not sure why I'm getting this error. Or perhaps there is different and simpler way to toggle the fill for plotly graphs?
ui.R
shinyUI(fluidPage(
titlePanel("Snow Weather Stations"),
mainPanel(
plotlyOutput("testplot", height = "500px")
)
)
)
server.R
library(shiny)
library(plotly)
library(dplyr)
library(tidyr)
csvf <- read.csv(file = "http://bcrfc.env.gov.bc.ca/data/asp/realtime/data/SW.csv",
check.names = FALSE, stringsAsFactors = FALSE)
swe <- csvf %>%
gather(STATION, SWE, -1) %>%
separate(`DATE (UTC)`, c('DATE', 'TIME'), sep = " ") %>%
filter(TIME == "15:00:00") %>%
select(-TIME) %>%
filter(substr(STATION,1,2) == "1A")
swe$DATE <- as.Date(swe$DATE)
swe$HOVERTEXT <- paste(swe$STATION, paste0(swe$SWE, " mm"), sep = "<br>")
xmin <- as.numeric(as.Date("2015-10-01")) * 24 * 60 * 60 * 1000
xmax <- as.numeric(as.Date("2016-09-30")) * 24 * 60 * 60 * 1000
shinyServer(function(input, output) {
output$testplot <- renderPlotly({
plot_ly(swe, x = DATE, y = SWE, group = STATION,
line = list(color = '#CCCCCC'),
text = HOVERTEXT, hoverinfo = "text+x",
hoveron = "points",
key = STATION) %>%
layout(showlegend = FALSE,
hovermode = 'closest',
xaxis = list(title = "",
showgrid = FALSE, showline = TRUE,
mirror = "ticks", ticks = "inside", tickformat = "%b",
hoverformat = "%b %-d",
range = c(xmin, xmax)),
yaxis = list(title = "Snow Water Equivalent (mm)",
showgrid = FALSE, showline = TRUE,
mirror = "ticks", ticks = "inside",
rangemode = "tozero")) %>%
config(displayModeBar = FALSE)
d <- event_data("plotly_hover")
if (is.null(d)) {
stn <- "1A01P Yellowhead Lake"
} else {
stn <- d$key[1]
}
add_trace(filter(swe, STATION == stn), x = DATE, y = SWE,
line = list(color = "404040"), fill = "tozeroy")
})
})

Related

Firefox Leaflet Not Displaying Map Shapes in Shiny App Default Page When Published on shinyapps.io (other browsers are working fine)

I've just created my first Shiny app and published to the Internet - https://craycrayjodie.shinyapps.io/MapApp/
When launching the app and viewing in Chrome and I.E the default page ('Map' tab) loads as expected - with the "March" data displayed on the map. This is specified in the sliderTextInput for the page.
However, when I load the app and view in Firefox (i.e. the 'Map' tab), the "March" data is not displayed on the map when the app loads by default in Firefox. I need to move the sliderTextInput, then the data loads on the map in the Browser.
This is only an issue for Firefox, the other browsers (i.e. Chrome and IE) are fine and have the March data loaded and displayed on the map when the default 'Map' page loads.
I have published my files up to GitHub - https://github.com/craycrayjodie/DataVis
Also, my app.R logic is as follows:
library(dplyr)
library(lubridate)
library(sf)
library(leaflet)
library(shinythemes)
library(RColorBrewer)
library(shinyWidgets)
library(rmapshaper)
library(rsconnect)
library(shiny)
library(ggplot2)
library(highcharter)
library(magrittr)
library(htmlwidgets)
library(RColorBrewer)
library(shinycssloaders)
###################################################################################################
myAusdata_by_month_sf = readRDS("myAusdata_by_month.rds") #load previously saved datafile
myAusdata_by_month_5 = readRDS("myAusdata_by_month_5.rds") #load previously saved datafile
areas_by_weeks = readRDS("areas_by_weeks.rds") #load previously saved datafile
# Options for Spinner
options(spinner.color="pink", spinner.type = 7, spinner.color.background="#ffffff", spinner.size=1)
ui <- shinyUI(
navbarPage(
title = "Australians Mobility Changes During COVID",
theme = shinytheme("yeti"),
tabPanel("Map",
div(class = "outer",
tags$head(
includeCSS("styles.css")
),
leafletOutput("map", width = "100%", height = "100%"),
absolutePanel(bottom = 30, left = 250, draggable = TRUE,
# slider title, step increments
sliderTextInput("choices", "Select month:", choices = unique(myAusdata_by_month_sf$month),
animate = animationOptions(interval = 1500, loop = FALSE), grid = TRUE, selected = "March", width = 400))
),
tags$div(id = "cite",
'Data downloaded from Facebook for Good by Jodie Anderson (2020).'
)
),
tabPanel("Story",
highchartOutput("timeline", height = "800px" ) %>% withSpinner(),
includeMarkdown("analysis.md"),
br()
),
tabPanel("Heatmap",
highchartOutput("heatmap", height = "100%") %>% withSpinner(),
br()
),
tabPanel("About",
includeMarkdown("about.md"),
br()
)
)
)
# Define server logic
server <- function(input, output, session) {
filteredData <- reactive({
myAusdata_by_month_sf %>%
filter(month %in% input$choices)
})
popup <- reactive({
sprintf("%s: %.1f%%", filteredData()$polygon_name, filteredData()$AvRelChange*100)
})
output$map <- renderLeaflet({
mypalette <- colorNumeric(palette = "PuOr", domain = myAusdata_by_month_sf$AvRelChange, na.color = "transparent")
leaflet(myAusdata_by_month_sf) %>%
setView(134, -29, 4) %>%
addProviderTiles("Esri.WorldGrayCanvas") %>%
addLegend(pal=mypalette, values=~AvRelChange, opacity=1, title = "Mobility Change (%)", position = "bottomleft",
labFormat = labelFormat(prefix = "(", suffix = ")", between = ", ",
transform = function(x) 100 * x))
})
observe({
mypalette <- colorNumeric(palette = "PuOr", domain = myAusdata_by_month_sf$AvRelChange, na.color = "transparent")
leafletProxy("map", data = filteredData()) %>%
clearShapes() %>%
addPolygons(fillColor = ~mypalette(AvRelChange),
stroke=TRUE,
fillOpacity = 1,
color = "grey",
weight = 0.3,
label = popup(), labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "2px 2px"),
textsize = "13px",
direction = "auto", offset = c(20, -25)))
})
output$timeline <- renderHighchart ({
hc <- myAusdata_by_month_5 %>%
hchart ('spline', hcaes(x= date, y=AvRelChange, group=NAME_1)) %>%
hc_colors(brewer.pal(8, "Dark2")) %>%
hc_title(text="Australians Mobility Changes", style=list(fontWeight="bold", fontSize="30px"),
align="left") %>%
hc_subtitle(text="During the coronavirus pandemic", style=list(fontWeight="bold"), align="left") %>%
hc_xAxis(title = list(text=NULL), plotBands = list(list(label = list(text = "Australia<br>in<br>lockdown"), color = "rgba(100, 0, 0, 0.1)",from = datetime_to_timestamp(as.Date('2020-03-16', tz = 'UTC')),
to = datetime_to_timestamp(as.Date('2020-03-31', tz = 'UTC'))))) %>%
hc_yAxis(title=list(text = "Mobility Change (%)"), showLastLabel = FALSE, labels = list(format = "{value}%")) %>%
hc_caption(text = "The Change in Mobility metric looks at how much people are moving around and compares it to a baseline period that predates most social distancing measures.<br>
The baseline period for this dataset is the four weeks of February 2020 (i.e. from the 2nd to the 29th).", useHTML = TRUE)%>%
hc_credits(text = "www.highcharts.com", href = "www.highcharts.com", enabled = TRUE, style = list(fontSize="10px")) %>%
hc_tooltip(crosshairs = TRUE, borderWidth = 2, valueSuffix = "%") %>%
hc_navigator(enabled = TRUE) %>%
hc_rangeSelector(enabled = TRUE) %>%
hc_plotOptions(series = list(marker = list(enabled = FALSE), lineWidth = 4)) %>%
hc_add_annotation(labels = list(list(point = list(xAxis = 0,yAxis = 0,x = datetime_to_timestamp(as.Date('2020-07-13', tz = 'UTC')),y = 7),shape = "rect", text = "10th July: QLD opens borders", useHTML = TRUE))) %>%
hc_add_annotation(labels = list(list(point = list(xAxis = 0,yAxis = 0,x = datetime_to_timestamp(as.Date('2020-07-20', tz = 'UTC')),y = -22),shape = "rect", text = "30th June: Vic in lockdown", useHTML = TRUE))) %>%
hc_add_annotation(labels = list(list(point = list(xAxis = 0,yAxis = 0,x = datetime_to_timestamp(as.Date('2020-08-20', tz = 'UTC')),y = -30),shape = "rect", text = "2nd Aug: Vic restrictions ease", useHTML = TRUE))) %>%
hc_add_annotation(labels = list(list(point = list(xAxis = 0,yAxis = 0,x = datetime_to_timestamp(as.Date('2020-11-14', tz = 'UTC')),y = -41),shape = "rect", text = "16th Nov: SA restrictions in place<br>21st Nov: SA restrictions lifted", useHTML = TRUE)))
hc
})
output$heatmap <- renderHighchart ({
hc1 <- areas_by_weeks %>%
hchart(type = "heatmap", hcaes(x = date, y = polygon_name, value = AvRelChange)) %>%
hc_title(text="Australians Mobility Changes", style=list(fontWeight="bold", fontSize="30px"), align="left") %>%
hc_subtitle(text="During the coronavirus pandemic", style=list(fontWeight="bold"), align="left") %>%
hc_boost(useGPUTranslations = TRUE) %>%
hc_size(height = 5000, width = 550) %>%
hc_colorAxis(labels = list(format = '{value}%'), stops = color_stops(10, rev(brewer.pal(10, "RdBu")))) %>%
hc_legend(itemMarginTop = 75, layout = "vertical", verticalAlign = "top", align = "right", valueDecimals = 0) %>%
hc_xAxis(labels = list(enabled = FALSE), tickInterval = 5, title = NULL, lineWidth = 0, tickLength = 20) %>%
hc_yAxis(title=list(text = ""), reversed = TRUE, gridLineWidth = 0) %>%
hc_tooltip(pointFormat = '{point.date} <br> {point.polygon_name}: <b>{point.value} %') %>%
hc_credits(position = list(align = 'center', x = 135, y = -4), text = "www.highcharts.com", href = "http://www.highcharts.com", enabled = TRUE, style = list(fontSize="10px")) %>%
hc_caption(align = 'center', text = "The white coloured boxes in the heatmap represent gaps in data.", useHTML = TRUE)
hc1
})
}
# Run the application
shinyApp(ui = ui, server = server)
If a clever cookie can please advise on what changes I need to make to get the app working when the page loads with Firefox, that would be fabulous :)

How to trigger a re-render of a plot when a column content of the plotted data changes with the use of reactive element

In the following app the user can select points in the plot by dragging, which should swap their Selected state between 0 and 1
points will get a shape and color depending on their 0 / 1 state, as a visual support for a user to select/deselect model parameters for the next model run.
in the version of the plots I had in my real app, the plotted data is a reactive variable values$RFImp_FP1 but I found out that the plot does not re-render when the content of column Selected of that data.table (or data.frame) changes.
Therefore I am trying to change it to a reactive object, but I'm failing to figure out how to change the Selected column of reactive data.table `RFImp
my attempts (comments in the code) so far produce either an assign error, or an infinite loop.
P.S.: Since i'm coding the stuff with lapply as I am using the code block several times in my app (identical "modules" with different serial number and using different data as the app takes the user through sequential stages of processing data), the second approach with values (app 2) has my preference as this allows me to do things like this:
lapply(c('FP1', 'FP2'), function(FP){
values[[paste('RFAcc', FP, sep = '_')]] <- ".... code to select a dataframe from model result list object values[[paste('RFResults', FP, sep = '_']]$Accuracy...."
which as far as I know can't be done with objectname <- reactive({....}) as you can't paste on the left side of the <- here
REACTIVE OBJECT APPROACH:
library(shiny)
library(plotly)
library(dplyr)
library(data.table)
ui <- fluidPage(
plotlyOutput('RFAcc_FP1', width = 450)
)
server <- function(input, output, session) {
values <- reactiveValues()
observe({
if(!is.null(RFImp_FP1()$Selected)) {
parsToChange <- event_data("plotly_selected", source = 'RFAcc_FP1')$y
if(!is.null(event_data("plotly_selected", source = 'RFAcc_FP1'))){
data_df <- RFImp_FP1()
data_df <- data_df %>% .[, Selected := if_else(Variables %in% parsToChange, 1-Selected, Selected)]
# how to get the reactive Data frame to update the selected
# values$Selected <- data_df$Selected #creates infinite loop.....
# RFImp_FP1$Selected <- data_df$Selected # throws an error
}
}
})
RFImp_FP1 <- reactive({
# in real app the dataframe RFImp_FP1 is a part of a list with randomForest results,
RFImp_FP1 <- data.table( MeanDecreaseAccuracy = runif(10, min = 0, max = 1), Variables = letters[1:10])
RFImp_FP1$Selected <- 1
# RFImp_FP1$Selected <- if(!is.null(values$Selected)){
# values$Selected } else {1 }
RFImp_FP1
})
output$RFAcc_FP1 <- renderPlotly({
RFImp_FP1()[order(MeanDecreaseAccuracy)]
RFImp_score <- RFImp_FP1()
plotheight <- length(RFImp_score$Variables) * 80
p <- plot_ly(data = RFImp_score,
source = 'RFAcc_FP1',
height = plotheight,
width = 450) %>%
add_trace(x = RFImp_score$MeanDecreaseAccuracy,
y = RFImp_score$Variables,
type = 'scatter',
mode = 'markers',
color = factor(RFImp_score$Selected),
colors = c('#1b73c1', '#797979'),
symbol = factor(RFImp_score$Selected),
symbols = c('circle','x'),
marker = list(size = 6),
hoverinfo = "text",
text = ~paste ('<br>', 'Parameter: ', RFImp_score$Variables,
'<br>', 'Mean decrease accuracy: ', format(round(RFImp_score$MeanDecreaseAccuracy*100, digits = 2), nsmall = 2),'%',
sep = '')) %>%
layout(
margin = list(l = 160, r= 20, b = 70, t = 50),
hoverlabel = list(font=list( color = '#1b73c1'), bgcolor='#f7fbff'),
xaxis = list(title = 'Mean decrease accuracy index (%)',
tickformat = "%",
showgrid = F,
showline = T,
zeroline = F,
nticks = 5,
font = list(size = 8),
ticks = "outside",
ticklen = 5,
tickwidth = 2,
tickcolor = toRGB("black")
),
yaxis = list(categoryarray = RFImp_score$Variables,
autorange = T,
showgrid = F,
showline = T,
autotick = T,
font = list(size = 8),
ticks = "outside",
ticklen = 5,
tickwidth = 2,
tickcolor = toRGB("black")
),
dragmode = "select"
) %>% add_annotations(x = 0.5,
y = 1.05,
textangle = 0,
font = list(size = 14,
color = 'black'),
text = "Contribution to accuracy",
showarrow = F,
xref='paper',
yref='paper')
p <- p %>% config(displayModeBar = F)
p
})
}
shinyApp(ui, server)
PREVIOUS reactiveValues() approach:
as you can see, with this app, the plot does not update when selecting a region in the plot even though the code changes the content of column Selected
ui <- fluidPage(
actionButton(inputId = 'Go', label = 'Go'),
plotlyOutput('RFAcc_FP1', width = 450)
)
server <- function(input, output, session) {
values <- reactiveValues()
observe({
if(!is.null(values$RFImp_FP1)) {
parsToChange <- event_data("plotly_selected", source = 'RFAcc_FP1')$y
if(!is.null(event_data("plotly_selected", source = 'RFAcc_FP1'))){
data_df <- values$RFImp_FP1
data_df <- data_df %>% .[, Selected := if_else(Variables %in% parsToChange, 1-Selected, Selected)]
values$RFImp_FP1 <- data_df
}
}
})
observeEvent(input$Go, {
values$RFImp_FP1 <- data.table(MeanDecreaseAccuracy = runif(10, min = 0, max = 1), Variables = letters[1:10])
values$RFImp_FP1$Selected <- 1
})
output$RFAcc_FP1 <- renderPlotly({
if(!is.null(values$RFImp_FP1)) {
RFImp_score <- values$RFImp_FP1[order(MeanDecreaseAccuracy)]
plotheight <- length(RFImp_score$Variables) * input$testme
p <- plot_ly(data = RFImp_score,
source = 'RFAcc_FP1',
height = plotheight,
width = 450) %>%
add_trace(x = RFImp_score$MeanDecreaseAccuracy,
y = RFImp_score$Variables,
type = 'scatter',
mode = 'markers',
color = factor(RFImp_score$Selected),
colors = c('#1b73c1', '#797979'),
symbol = factor(RFImp_score$Selected),
symbols = c('circle','x'),
marker = list(size = 6),
hoverinfo = "text",
text = ~paste ('<br>', 'Parameter: ', RFImp_score$Variables,
'<br>', 'Mean decrease accuracy: ', format(round(RFImp_score$MeanDecreaseAccuracy*100, digits = 2), nsmall = 2),'%',
sep = '')) %>%
layout(
margin = list(l = 160, r= 20, b = 70, t = 50),
hoverlabel = list(font=list( color = '#1b73c1'), bgcolor='#f7fbff'),
xaxis = list(title = 'Mean decrease accuracy index (%)',
tickformat = "%",
showgrid = F,
showline = T,
zeroline = F,
nticks = 5,
font = list(size = 8),
ticks = "outside",
ticklen = 5,
tickwidth = 2,
tickcolor = toRGB("black")
),
yaxis = list(categoryarray = RFImp_score$Variables,
autorange = T,
showgrid = F,
showline = T,
autotick = T,
font = list(size = 8),
ticks = "outside",
ticklen = 5,
tickwidth = 2,
tickcolor = toRGB("black")
),
dragmode = "select"
) %>% add_annotations(x = 0.5,
y = 1.05,
textangle = 0,
font = list(size = 14,
color = 'black'),
text = "Contribution to accuracy",
showarrow = F,
xref='paper',
yref='paper')
p$elementId <- NULL ## to surpress warning of widgetid
p <- p %>% config(displayModeBar = F)
p
} else {
p <- plot_ly( type = 'scatter', mode = 'markers', height = '400px', width = 450) %>% layout(
margin = list(l = 160, r= 20, b = 70, t = 50),
xaxis = list(title = 'Mean decrease accuracy index', range= c(0,1), nticks = 2, showline = TRUE),
yaxis = list(title = 'Model input variables', range = c(0,1), nticks = 2, showline = TRUE)) %>%
add_annotations(x = 0.5, y = 1.1, textangle = 0, font = list(size = 14, color = 'black'),
text = 'Contribution to accuracy',
showarrow = F, xref='paper', yref='paper')
p$elementId <- NULL
p <- p %>% config(displayModeBar = F)
p}
})
}
shinyApp(ui, server)
Not sure if this is what you want (it´s a bit weird that the plot updates with random numbers after selecting points ;-) ), but I hope it helps.
Instead of using a normal observer I use observeEvent that fires when selecting something in the plot. I generally prefer observeEvent to catch an event. This triggers an update ob a reactiveValues value, which will initially be NULL
library(shiny)
library(plotly)
library(dplyr)
library(data.table)
testDF <- data.table( MeanDecreaseAccuracy = runif(10, min = 0, max = 1), Variables = letters[1:10])
testDF$Selected <- T
ui <- fluidPage(
plotlyOutput('RFAcc_FP1', width = 450)
)
server <- function(input, output, session) {
values <- reactiveValues(val = NULL)
observeEvent(event_data("plotly_selected", source = 'RFAcc_FP1')$y, {
values$val <- runif(1, min = 0, max = 1)
})
RFImp_FP1 <- reactive({
RFImp_FP1 <- testDF
if(!is.null(values$val)) {
parsToChange <- event_data("plotly_selected", source = 'RFAcc_FP1')$y
RFImp_FP1 <- RFImp_FP1 %>% .[, Selected := if_else(Variables %in% parsToChange, 1-Selected, Selected)]
} else { }
# in real app the dataframe RFImp_FP1 is a part of a list with randomForest results,
RFImp_FP1
# RFImp_FP1$Selected <- if(!is.null(values$Selected)){
# values$Selected } else {1 }
})
output$RFAcc_FP1 <- renderPlotly({
RFImp_score <- RFImp_FP1()[order(MeanDecreaseAccuracy)]
plotheight <- length(RFImp_score$Variables) * 80
p <- plot_ly(data = RFImp_score,
source = 'RFAcc_FP1',
height = plotheight,
width = 450) %>%
add_trace(x = RFImp_score$MeanDecreaseAccuracy,
y = RFImp_score$Variables,
type = 'scatter',
mode = 'markers',
color = factor(RFImp_score$Selected),
colors = c('#1b73c1', '#797979'),
symbol = factor(RFImp_score$Selected),
symbols = c('circle','x'),
marker = list(size = 6),
hoverinfo = "text",
text = ~paste ('<br>', 'Parameter: ', RFImp_score$Variables,
'<br>', 'Mean decrease accuracy: ', format(round(RFImp_score$MeanDecreaseAccuracy*100, digits = 2), nsmall = 2),'%',
sep = '')) %>%
layout(
margin = list(l = 160, r= 20, b = 70, t = 50),
hoverlabel = list(font=list( color = '#1b73c1'), bgcolor='#f7fbff'),
xaxis = list(title = 'Mean decrease accuracy index (%)',
tickformat = "%",
showgrid = F,
showline = T,
zeroline = F,
nticks = 5,
font = list(size = 8),
ticks = "outside",
ticklen = 5,
tickwidth = 2,
tickcolor = toRGB("black")
),
yaxis = list(categoryarray = RFImp_score$Variables,
autorange = T,
showgrid = F,
showline = T,
autotick = T,
font = list(size = 8),
ticks = "outside",
ticklen = 5,
tickwidth = 2,
tickcolor = toRGB("black")
),
dragmode = "select"
) %>% add_annotations(x = 0.5,
y = 1.05,
textangle = 0,
font = list(size = 14,
color = 'black'),
text = "Contribution to accuracy",
showarrow = F,
xref='paper',
yref='paper')
p <- p %>% config(displayModeBar = F)
p
})
}
shinyApp(ui, server)

plotly plot doesnt show up

I am trying to animate this test data.frame but the plotly plot doesn't even show up! The same code works for original plotly data though. I have doublechecked column's class and they are the same as plotly example. I am now puzzled why this fails.
This also works in marker mode but not in lines mode as you see.
total <- data.frame(replicate(4,sample(0:1, 100, rep=TRUE)))
names(total) <- c("date", "frame", "P1.10", "year")
total$date <- as.numeric(as.character(t(rbind(runif(100, min=2000, max=2010)))))
f.rank <- order(total$date)
total$frame[f.rank] <- 1:nrow(total)
total$P1.10 <- as.numeric(as.character(t(rbind(runif(100, min=1, max=10)))))
total$year <- 2000
p <- total %>%
plot_ly(
x = ~date,
y = ~P1.10,
frame = ~frame,
type = 'scatter',
mode = 'lines',
line = list(simplyfy = F)
) %>%
layout(
xaxis = list(
title = "Date",
zeroline = F
),
yaxis = list(
title = "P1.10",
zeroline = F
)
) %>%
animation_opts(
frame = 100,
transition = 0,
redraw = FALSE
) %>%
animation_slider(
hide = T
) %>%
animation_button(
x = 1, xanchor = "right", y = 0, yanchor = "bottom"
)
You have ignored accumulate_by in the example. You also need an ID field. This is the same but using ggplot in combination.
set.seed(123)
library(plotly)
total <- data.frame(replicate(4,sample(0:1, 100, rep=TRUE)))
names(total) <- c("date", "frame", "P1.10", "year")
total$date <- as.numeric(as.character(t(rbind(runif(100, min=2000, max=2010)))))
f.rank <- order(total$date)
total$frame[f.rank] <- 1:nrow(total)
total$ID[f.rank] <- 1:nrow(total)
total$P1.10 <- as.numeric(as.character(t(rbind(runif(100, min=1, max=10)))))
total$year <- 2000
accumulate_by <- function(dat, var) {
var <- lazyeval::f_eval(var, dat)
lvls <- plotly:::getLevels(var)
dats <- lapply(seq_along(lvls), function(x) {
cbind(dat[var %in% lvls[seq(1, x)], ], frame = lvls[[x]])
})
dplyr::bind_rows(dats)
}
total <- total %>%
accumulate_by(~ID)
p <- ggplot(total,aes(ID, P1.10, frame = frame)) +
geom_line()
p <- ggplotly(p) %>%
layout(
title = "",
yaxis = list(
title = "P1.10",
zeroline = F,
tickprefix = "$"
),
xaxis = list(
title = "Date",
zeroline = F,
showgrid = F
)
) %>%
animation_opts(
frame = 100,
transition = 0,
redraw = FALSE
) %>%
animation_slider(
currentvalue = list(
prefix = "Day "
)
)

Shiny Plotly output that changes depending on conditions

I'm trying to make a shiny app for some user-friendly data analysis of some data I have, and I'd like to change the outputted Plotly plot depending on which file i'm looking at. Basically, I'd like to have one plot outputted at a time, where I can cycle through several plots (that don't change place in my shiny app) depending on which folder and criteria i'm using. Currently I'm struggeling with this, and I don't know exactly what to do from here. I've attached a few images to clarify what I mean and what I want.
This photo shows my UI and how I want my figures to be displayed. I'd like all figures to show in that same location, depending on the selected file.
When I switch to 'Datalogger', a new plot is generated, and it is outputted below the first one. I'd like it to be placed on top of it, in the exact same location.
Any help you can offer would be very welcome.
Best,
T.
Script:
# Load packages
library(shiny)
library(shinythemes)
library(dplyr)
library(readr)
library(lubridate)
library(plotly)
#picarro
time = as.character(seq(as.POSIXct("2018-06-01 12:00:00"), as.POSIXct("2018-06-01 12:10:00"), by=seconds() )); ch4.corr = runif(length(time), 1980, 2000);
data = data.frame(time, ch4.corr); data$time = as.POSIXct(time);
#datalogger
time = as.character(seq(as.POSIXct("2018-06-01 12:00:00"), as.POSIXct("2018-06-01 12:10:00"), by=seconds() )); PressureOut = runif(length(time), 1010, 1020);
dlog = data.frame(time, PressureOut); dlog$time = as.POSIXct(time);
#dronelog
time = as.character(seq(as.POSIXct("2018-06-01 12:00:00"), as.POSIXct("2018-06-01 12:10:00"), by=seconds() ));
ulog = data.frame(time); ulog$time = as.POSIXct(time);
#------------------------------------------------------------------------------
ui <- fluidPage(
titlePanel("Active AirCore analysis"),
hr(),
fluidRow(
column(3,
radioButtons("fileInput", "File",
choices = c("Picarro", "Datalogger", "Dronelog"),
selected = "Picarro"),
hr(),
conditionalPanel(
condition = "input.fileInput == 'Picarro'",
sliderInput("timeInputPicarro", "Time", as.POSIXct(data$time[1]), as.POSIXct(data$time[length(data$time)]), c(as.POSIXct(data$time[1])+minutes(1), as.POSIXct(data$time[length(data$time)])-minutes(1)), timeFormat = "%H:%M:%S", ticks = T, step = seconds(1), pre = "")),
conditionalPanel(
condition = "input.fileInput == 'Datalogger'",
sliderInput("timeInputDatalogger", "Time", as.POSIXct(dlog$time[1]), as.POSIXct(dlog$time[length(dlog$time)]), c(as.POSIXct(dlog$time[1]), as.POSIXct(dlog$time[length(dlog$time)])), timeFormat = "%H:%M:%S", ticks = T, step = seconds(1), pre = "")),
conditionalPanel(
condition = "input.fileInput == 'Dronelog'",
sliderInput("timeInputDronelog", "Time", as.POSIXct(ulog$time[1]), as.POSIXct(ulog$time[length(ulog$time)]), c(as.POSIXct(ulog$time[1])+minutes(1), as.POSIXct(ulog$time[length(ulog$time)])-minutes(1)), timeFormat = "%H:%M:%S", ticks = T, step = seconds(1), pre = "")),
hr(),
conditionalPanel(
condition = "input.fileInput == 'Picarro'",
radioButtons("picarroPlotInput", "Plot type",
choices = c("Time-series", "Process"),
selected = "Time-series")),
conditionalPanel(
condition = "input.fileInput == 'Datalogger'",
radioButtons("dataloggerPlotInput", "Plot type",
choices = c("Time-series", "Altitude"),
selected = "Time-series")),
hr(),
checkboxGroupInput(inputId='sidebarOptions',
label=('Options'),
choices=c('Blabla', 'Store data', 'BlablaBla')),
hr()),
br(),
mainPanel(
plotlyOutput("dataplot"),
hr(),
plotlyOutput("dlogplot")
)
)
)
server <- function(input, output, session) {
datasetInputPic <- reactive({ data = data; })
datasetInputPicSamp <- reactive({ dat = data[(data$time>=input$timeInputPicarro[1]) & (data$time<=input$timeInputPicarro[2]),]; })
datasetInputDatalogger <- reactive({ dlog = dlog })
datasetInputDronelog <- reactive({ ulog = ulog })
output$dataplot <- renderPlotly({
if( (input$fileInput == 'Picarro' ) & (input$picarroPlotInput == 'Time-series')){
data = datasetInputPic();
data$time = as.POSIXct(data$time);
dat = datasetInputPicSamp();
dat$time = as.POSIXct(dat$time);
sec.col = "red";
f = list(size = 8);
x <- list(title = " ")
y <- list(title = "CH<sub>4</sub> [ppb]")
p2 = plot_ly() %>%
add_trace(data = data,
x = ~time,
y = ~ch4.corr,
type = 'scatter',
mode = "markers",
marker = list(size = 3, color = 'black')) %>%
add_trace(data = dat,
x = ~time,
y = ~ch4.corr,
type = 'scatter',
mode = "markers",
marker = list(size = 3, color = sec.col)) %>%
layout(xaxis = x, yaxis = y, title = '', showlegend = F, titlefont = f);
s1 = subplot(p2, margin = 0.06,nrows=1,titleY = TRUE) %>%
layout(showlegend = F, margin = list(l=50, r=0, b=50, t=10), titlefont = f);
s1
}
})
output$dlogplot <- renderPlotly({
if( (input$fileInput == 'Datalogger' ) & (input$dataloggerPlotInput == 'Time-series')){
data = datasetInputDatalogger();
data$time = as.POSIXct(data$time);
x <- list(title = " ")
y <- list(title = "Outside pressure [mbar]")
p1 = plot_ly() %>%
add_trace(data = data,
y = ~PressureOut,
x = ~time,
type = 'scatter',
mode = "markers",
marker = list(size = 3, color = 'black'));
s1 = subplot(p1, margin = 0.07, nrows=2, titleY = TRUE, titleX = FALSE)
layout(s1, showlegend = F, margin = list(l=100, r=100, b=0, t=100), title = "Datalogger data")
s1
}
})
outputOptions(output, c("dataplot", "dlogplot"), suspendWhenHidden = TRUE)
}
runApp(list(ui = ui, server = server))
Your issue is that in your ui you have written:
mainPanel(
plotlyOutput("dataplot"),
hr(),
plotlyOutput("dlogplot")
)
Using this structure, the "dlogplot" will always display below the "dataplot" because you essentially gave it its own position in the main panel that is below the "dataplot". One solution, if you want the plots to be displayed in the same exact spot when clicking the various buttons, is to give only one plotlyOutput. Next you would put conditional if, else if and else in renderPlotly. For example:
output$dataplot <- renderPlotly({
if( (input$fileInput == 'Picarro' ) & (input$picarroPlotInput == 'Time-series')){
data = datasetInputPic();
data$time = as.POSIXct(data$time);
dat = datasetInputPicSamp();
dat$time = as.POSIXct(dat$time);
sec.col = "red";
f = list(size = 8);
x <- list(title = " ")
y <- list(title = "CH<sub>4</sub> [ppb]")
p2 = plot_ly() %>%
add_trace(data = data,
x = ~time,
y = ~ch4.corr,
type = 'scatter',
mode = "markers",
marker = list(size = 3, color = 'black')) %>%
add_trace(data = dat,
x = ~time,
y = ~ch4.corr,
type = 'scatter',
mode = "markers",
marker = list(size = 3, color = sec.col)) %>%
layout(xaxis = x, yaxis = y, title = '', showlegend = F, titlefont = f);
s1 = subplot(p2, margin = 0.06,nrows=1,titleY = TRUE) %>%
layout(showlegend = F, margin = list(l=50, r=0, b=50, t=10), titlefont = f);
s1
}
else if( (input$fileInput == 'Datalogger' ) & (input$dataloggerPlotInput == 'Time-series')){
data = datasetInputDatalogger();
data$time = as.POSIXct(data$time);
x <- list(title = " ")
y <- list(title = "Outside pressure [mbar]")
p1 = plot_ly() %>%
add_trace(data = data,
y = ~PressureOut,
x = ~time,
type = 'scatter',
mode = "markers",
marker = list(size = 3, color = 'black'));
s1 = subplot(p1, margin = 0.07, nrows=2, titleY = TRUE, titleX = FALSE)
layout(s1, showlegend = F, margin = list(l=100, r=100, b=0, t=100), title = "Datalogger data")
s1
}
})
This code will put the "dlogplot" and the "dataplot" in the same position in your main panel. (You would also need to get rid of output$dlogplot <- renderPlotly({...}) so that it isn't also trying to make that plot.)
Try this out and see if it works for your purposes.

Render blank plot using plot_geo() in ShinyApp R

I am doing my final project for data visualization.
I would like to render a map with markers on it using Plotly in ShinyApp. The function I am using is plot_geo(). However, the plot works perfectly in the normal R environment, but it fails to render in ShinyApp, only displaying the blank plot. And also no error message is reported.
I have been stuck here for long. Can anyone help? Thanks!
My code (ShinyApp)
library(shiny)
library(plotly)
library(RColorBrewer)
library(ggplot2)
# Define UI for application
ui <- fluidPage(
# Application title
titlePanel("Times University Ranking"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
selectInput("year",
"Select a year",
c(2011:2016))
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("map")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
times <- data.frame(read.csv("./times.csv", header = TRUE))
d <- reactive({
a <- subset(times, year == input$year)
return (a)
})
g <- list(
scope = 'world',
projection = list(type = 'Mercator'),
showframe = FALSE,
showland = TRUE,
showsubunits = TRUE,
landcolor = toRGB("gray95"),
subunitcolor = toRGB("gray85"),
countrycolor = toRGB("gray65"),
countrywidth = 0.5,
subunitwidth = 0.5
)
output$map <- renderPlotly({
p <- plot_geo(data = d(), lat = ~lat, lon = ~lon,
color = ~as.numeric(rescale),
mode = 'markers', colors = "Spectral") %>%
add_markers(text = ~paste(paste("Rank:", world_rank),
university_name, country,
year, sep = "<br />"),
hoverinfo = "text") %>%
colorbar(title = "World Rank") %>%
layout(title = paste(input$year, "Times University Ranking on the Map"),
geo = g)
})
}
# Run the application
shinyApp(ui = ui, server = server)
Normal R code
library(plotly)
library(RColorBrewer)
input <- read.csv("times.csv", header = TRUE)
df <- data.frame(subset(input, year == 2015))
df <- df[sort.int(df$No, decreasing = TRUE), ]
# geo styling
g <- list(
scope = 'world',
projection = list(type = 'Mercator'),
showframe = FALSE,
showland = TRUE,
showsubunits = TRUE,
landcolor = toRGB("gray95"),
subunitcolor = toRGB("gray85"),
countrycolor = toRGB("gray65"),
countrywidth = 0.5,
subunitwidth = 0.5
)
p <- plot_geo(data = df, lat = ~lat,
lon = ~lon, color = ~as.numeric(rescale), mode = 'markers',
colors = "Spectral") %>%
add_markers(
text = ~paste(paste("Rank:", world_rank), university_name,
country, year, sep = "<br />"),
hoverinfo = "text") %>%
colorbar(title = "World Rank") %>%
layout(title = '2016 Times University Rankings on the map', geo = g)

Resources