I am building an app with many charts and using spinners while waiting for them to generate.
I found if I add spinner to the charts, my date input no longer works.
I dont understand this behaviour, nor know how to fix it.
Here is my example:
library(data.table)
library(tidyverse)
library(shinydashboard)
library(highcharter)
library(lubridate)
library(shiny)
library(shinyWidgets)
library(shinycssloaders)
db <- mtcars
sidebar <- dashboardSidebar()
body <- dashboardBody(
h2("Test"),
box(title = "Date",width =12,
column(dateInput('startdate','',value = dmy("1/1/2017"), min = NULL, max = NULL,
format = "yyyy-mm-dd", startview = "month", weekstart = 0,language = "en", width = NULL),width = 3)
),
highchartOutput("hc")%>%withSpinner()
)
header <- dashboardHeader()
ui <- dashboardPage(header,sidebar,body)
server <- function(input, output, session) {
output$hc <- renderHighchart({
hc <- highchart() %>%
hc_add_series(name = "mpg", data = db$mpg) %>%
hc_add_series(name = "wt", data = db$wt)
hc
})
}
shinyApp(ui, server)
If I were to remove withSpinner(), I then can select the date.
I got a love-hate relationship with those spinners. Anyways: putting your graph in a fluidrow (and column) solved the problem for me:
library(data.table)
library(tidyverse)
library(shinydashboard)
library(highcharter)
library(lubridate)
library(shiny)
library(shinyWidgets)
library(shinycssloaders)
db <- mtcars
sidebar <- dashboardSidebar()
body <- dashboardBody(
h2("Test"),
box(title = "Date",width =12,
column(dateInput('startdate','',value = dmy("1/1/2017"), min = NULL, max = NULL,
format = "yyyy-mm-dd", startview = "month", weekstart = 0,language = "en", width = NULL),width = 3)
),
fluidRow(
column(
width = 12,
shinycssloaders::withSpinner(highchartOutput("hc"))
)
)
)
header <- dashboardHeader()
ui <- dashboardPage(header,sidebar,body)
server <- function(input, output, session) {
output$hc <- renderHighchart({
hc <- highchart() %>%
hc_add_series(name = "mpg", data = db$mpg) %>%
hc_add_series(name = "wt", data = db$wt)
hc
})
}
shinyApp(ui, server)
This is might suggest it was also weirdly applied to other aspects of your page rather than only your graph?
Related
I'm a beginner, which is worth mentioning at the beginning. I wanted to create an application in which the user enters an arbitrary date and, based on it, calculates the time between that date and the last activity of a person from the data table. if that time is greater than the value of input$disabled, which is the expected time of being offline, I would like to display all the information about those people. currently, I'm getting the following problem: Error in UseMethod: no applicable method for 'filter' applied to an object of class "c('reactiveExpr', 'reactive', 'function')" and for the second one: Error in UseMethod: no applicable method for 'mutate' applied to an object of class "difftime".
last_event has a character type and looks like this: "2019-12-22 00:00:0", which is why I overlay as.Date() on it. I am not sure if I used reactive() correctly, because this application is a work of trial and error. Can someone help me? I would be very grateful, because it is kinda frustrating for me right now.
last_event <- c("2019-12-26 00:00:00","2020-10-21 00:00:00","2020-05-27 00:00:01","2020-02-25 00:00:00","2020-10-09 00:00:00","2020-10-16 00:00:00","2019-12-01 00:00:01")
id <- c(1:7)
users_name <- c("Krox", "Minit", "Brulon", "Loc", "Mese02", "Robu78", "CoffeeMan")
data <- data.frame(id, users_name, last_event)
ui <- dashboardPage(
dashboardHeader(title = "X"),
dashboardSidebar(
dateInput(inputId = "date", label = "Podaj date : "),
sliderInput(inputId = "disabled", label = "Czas nieaktywnosci (msc): ", min = 6, max = 24, value = 12)),
dashboardBody(
dataTableOutput(outputId = "table")
))
server <- function(input, output){
reactive_data <- eventReactive(input$date, {
mutate(diff = (difftime(as.Date(input$date), as.Date(data$last_event)))/30)
data
})
output$table <- renderDataTable({
data <- reactive_data()
if (input$disabled){
data %>%
filter(diff > input$disabled)
}})
}
shinyApp(ui, server)
Also I try to write this code in another way:
library(shiny)
library(shinydashboard)
library(shinyWidgets)
library(readxl)
library(dplyr)
data <- read_excel(file.choose())
ui <- dashboardPage(
dashboardHeader(title = "X"),
dashboardSidebar(
dateInput(inputId = "date", label = "Podaj date : "),
sliderInput(inputId = "disabled", label = "Czas nieaktywnosci (msc): ", min = 6, max = 24, value = 12)),
dashboardBody(
dataTableOutput(outputId = "table")
))
server <- function(input, output){
data1 <- reactive(data %>%
mutate(diff = (difftime(as.Date(input$date)) - as.Date(data1$last_event))/30))
output$table <- renderDataTable(data1 %>%
filter(diff > input$disabled))
}
shinyApp(ui, server)
Please try the below:
last_event <- c("2019-12-26 00:00:00","2020-10-21 00:00:00","2020-05-27 00:00:01","2020-02-25 00:00:00","2020-10-09 00:00:00","2020-10-16 00:00:00","2019-12-01 00:00:01")
id <- c(1:7)
users_name <- c("Krox", "Minit", "Brulon", "Loc", "Mese02", "Robu78", "CoffeeMan")
data <- data.frame(id, users_name, last_event)
ui <- dashboardPage(
dashboardHeader(title = "X"),
dashboardSidebar(
dateInput(inputId = "date", label = "Podaj date : "),
sliderInput(inputId = "disabled", label = "Czas nieaktywnosci (msc): ", min = 6, max = 24, value = 12)),
dashboardBody(
dataTableOutput(outputId = "table")
))
server <- function(input, output){
reactive_data <- eventReactive(input$date, {
mutate(data, diff = (difftime(as.Date(input$date), as.Date(data$last_event)))/30)
})
output$table <- renderDataTable({
data <- reactive_data()
if (input$disabled){
data %>%
filter(diff > input$disabled)
}})
}
shinyApp(ui, server)
This line needed work:
mutate(data, diff = (difftime(as.Date(input$date), as.Date(data$last_event)))/30)
Alternatively:
data %>% mutate(diff = (difftime(as.Date(input$date), as.Date(data$last_event)))/30)
Update
for your second code example, see here:
library(shiny)
library(shinydashboard)
library(shinyWidgets)
library(readxl)
library(dplyr)
data <- read_excel(file.choose())
ui <- dashboardPage(
dashboardHeader(title = "X"),
dashboardSidebar(
dateInput(inputId = "date", label = "Podaj date : "),
sliderInput(inputId = "disabled", label = "Czas nieaktywnosci (msc): ", min = 6, max = 24, value = 12)),
dashboardBody(
dataTableOutput(outputId = "table")
))
server <- function(input, output){
data1 <- reactive(data %>%
mutate(diff = (difftime(as.Date(input$date), as.Date(data$last_event))/30)))
output$table <- renderDataTable(data1() %>%
filter(diff > input$disabled))
}
shinyApp(ui, server)
Actually I solved this problem by myself, but thank you all for answers. The final code looks like that:
library(shiny)
library(shinydashboard)
library(shinyWidgets)
library(readxl)
library(dplyr)
library(DT)
ui <- dashboardPage(
dashboardHeader(title = "X"),
dashboardSidebar(
dateInput(inputId = "date", label = "Choose date : "),
sliderInput(inputId = "disabled", label = "Choose time of inactivity: ", min = 6, max = 24, value = 12)),
dashboardBody(
dataTableOutput(outputId = "table")
))
server <- function(input, output){
data1 <- reactive(read_excel(file.choose()))
output$table <- renderDT({
data1() %>%
mutate(diff = (difftime(input$date, as.Date(last_event))/30)) %>%
filter(diff > input$disabled) %>%
select(-diff) %>%
DT::datatable(options(list(scrollX=TRUE)))
})
}
shinyApp(ui, server)
I have an app, which fetches data from an SQL-db, then allows the user to edit it, and this should be saved to the DB. In the repex I have used a CSV-file, but the logic should still be comparable.
However, the data is saved in the session once I edit the column value, but if I switch input or close the app and re-open, it's back to the original. Edits are not reflected in the summary table. What am I doing wrong?
# Load libraries
library(DT)
library(gt)
library(shiny)
library(shinydashboard)
library(dplyr)
# Load data (run once for replication; in real use case will be a DB-connection)
#gtcars_tbl <- gtcars
#write.csv(gtcars_tbl, "gtcars_tbl.csv", row.names = FALSE)
# Simple UI
sidebar <- dashboardSidebar(
sidebarMenu(
menuItem("Summary table", tabName = "summary", icon = icon("project-diagram")),
menuItem("Edit table", tabName = "edit", icon = icon("project-diagram")),
uiOutput("country")
)
)
body <- dashboardBody(
tabItems(
tabItem(tabName = "summary",
h2("Summary of GT Cars"),
gt_output(outputId = "gt_filt_tbl")
),
tabItem(tabName = "edit",
h2("Editer GT Cars"),
DTOutput("edit")
)
)
)
ui <- dashboardPage(
dashboardHeader(title = "GT Cars"),
sidebar,
body)
# Define server functions
server <- function(input, output, session) {
# Load data
gtcars_tbl <- read.csv("gtcars_tbl.csv")
countries <- sort(as.vector(unique(gtcars_tbl$ctry_origin)))
# Create dropdown output
output$country <- renderUI({
selectInput("country", "Country", countries)
})
# Create reactive table
gt_tbl_react <- reactiveVal(NULL)
gt_tbl_react(gtcars_tbl)
# Create filtered table
gt_filt_tbl <- reactive({
req(input$country)
gt_tbl_react() %>%
filter(ctry_origin == input$country)
})
# Render summary table
output$gt_filt_tbl <- render_gt({
gt_filt_tbl() %>%
group_by(ctry_origin, mfr) %>%
summarise(
N = n(),
Avg_HP = mean(hp),
MSRP = mean(msrp)
) %>%
gt(
rowname_col = "ctry_origin",
groupname_col = "mfr")
})
# Render editable table
output$edit <- renderDT(
gt_tbl_react() %>%
filter(ctry_origin == input$country),
selection = 'none', editable = TRUE,
rownames = TRUE,
extensions = 'Buttons'
)
observeEvent(input$edit_cell_edit, {
gtcars_tbl[input$edit_cell_edit$row,input$edit_cell_edit$col] <<- input$edit_cell_edit$value
write.csv(gtcars_tbl, "gtcars_tbl.csv", row.names = FALSE)
})
}
# Run app
shinyApp(ui, server)
The issue is that input$edit_cell_edit$row and input$edit_cell_edit$col are provided according to the subsetted dataframe that is displayed whereas you are changing the values on complete dataframe.
Use this in observeEvent -
observeEvent(input$edit_cell_edit, {
inds <- which(gtcars_tbl$ctry_origin == input$country)
gtcars_tbl[inds[input$edit_cell_edit$row],input$edit_cell_edit$col] <- input$edit_cell_edit$value
write.csv(gtcars_tbl, "gtcars_tbl.csv", row.names = FALSE)
})
I have a set of charts and several tables on a Shiny pages. What would be the best way to create a download button to allow user download all of them to one file (i.e pdf). I tried grid.arrange but I am not sure how to convert the highchart objects to grobs objects.
Samples of outputs are below:
library("shiny")
library("highcharter")
data(citytemp)
ui <- fluidPage(
fluidRow(
column(width = 8,
highchartOutput("hcontainer1",height = "500px")),
column(width = 8,
highchartOutput("hcontainer2",height = "500px")),
column(width = 8,
highchartOutput("hcontainer3",height = "500px")),
column(width = 12,dataTableOutput("table"))
)
)
server = function(input, output) {
output$hcontainer1 <- renderHighchart({
hc <- highcharts_demo() %>%
hc_rm_series("Berlin") %>%
hc_chart(type = "line")
hc
})
output$hcontainer2 <- renderHighchart({
hc <- highcharts_demo() %>%
hc_rm_series("Berlin") %>%
hc_chart(type = "bar")
hc
})
output$hcontainer3 <- renderHighchart({
hc <- highcharts_demo() %>%
hc_rm_series("Berlin") %>%
hc_chart(type = "column")
hc
})
output$table <- renderDataTable({
dt <- data.frame(iris[1:10,])
dt
})
}
shinyApp(ui = ui, server = server)
Just try putting a download button at each column. I am unable to install highcharter now so I didn't fully test the code. Let me know if you are having issues -
column(width = 8,
highchartOutput("hcontainer1",height = "500px"), downloadButton("downloadplot1", label = "Download"))
Write a separate function for generating the plot -
gen_plot <- function(series_name, chart_type){
hc <- highcharts_demo() %>%
hc_rm_series(series_name) %>%
hc_chart(type = chart_type)
hc
}
Now in server -
output$downloadplot1 <- downloadHandler(filename ="1.png",
content = function(file) {
png(file, width=800, height=800)
gen_plot("Berlin", "line")
dev.off()
},
contentType = "image/png")
I am trying to understand the reactive part in R shiny. In that process I am trying to update an output table based on the input change while selecting values from the age drop down. It seems to do it by the first value but when I change any value from the age drop down it won't update my table. The input I am using is chooseage. Below is the code which I am using.
library(shiny)
library(shinydashboard)
library(shinyBS)
library(knitr)
library(kableExtra)
library(shiny)
library(shinythemes)
ui <- dashboardPage(
dashboardHeader(disable = F, title = "PATH Study"),
dashboardSidebar(sidebarMenu(
menuItem(
"Population Filter",
uiOutput("choose_age")
)
)),
dashboardBody(box(
width = 12,
tabBox(
width = 12,
id = "tabBox_next_previous",
tabPanel("Initiation",
fluidRow(
box(
width = 5,
solidHeader = TRUE,
status = "primary",
tableOutput("smoke"),
collapsible = F
)
))
),
uiOutput("Next_Previous")
))
)
server <- function(input, output, session) {
# Drop-down selection box for which Age bracket to be selected
age_levels <- c("18 to 24 years old","25 to 34 years old","35 to 44 years old")
output$choose_age <- renderUI({
selectInput("selected_age", "Age", as.list(age_levels))
})
myData <- reactive({
with_demo_vars %>%
filter(age == input$choose_age) %>%
pct_ever_user(type = "SM")
})
output$smoke <-
renderTable({
head(myData())
})
}
shinyApp(ui = ui, server = server)
Here is a quick prototype for your task
library(shiny)
library(tidyverse)
library(DT)
# 1. Dataset
df_demo <- data.frame(
age = c(16, 17, 18, 19, 20),
name = c("Peter", "Mary", "Mike", "Nick", "Phillipe"))
# 2. Server
server <- function(input, output, session) {
# 1. UI element 'Age'
output$ui_select_age <- renderUI({
selectInput("si_age", "Age", df_demo$age)
})
# 2. Reactive data set
df_data <- reactive({
# 1. Read UI element
age_selected <- input$si_age
# 2. Filter data
df <- df_demo %>%
filter(age == age_selected)
# 3. Return result
df
})
# 3. Datatable
output$dt_table <- renderDataTable({
datatable(df_data())
})
}
# 3. UI
ui <- fluidPage(
fluidRow(uiOutput("ui_select_age")),
fluidRow(dataTableOutput("dt_table"))
)
# 4. Run app
shinyApp(ui = ui, server = server)
I think youre shinyApp is over-reactive, as all functions in the server are executed straight away, without waiting for any selected input. So either it will break down or behave weird. So you have to delay the reactivity with req(), validate() / need() or with any observeEvent or eventReactive() function.
Maybe this snippet might help you, although there would be several ways to achieve the desired behaviour.
library(shiny)
library(shinydashboard)
library(dplyr)
data(mtcars)
mtcars$age <- sample(x = c(10,20,30,40,50), size = nrow(mtcars), replace = T)
with_demo_vars <- mtcars
ui <- dashboardPage(
dashboardHeader(disable = F, title = "PATH Study"),
dashboardSidebar(sidebarMenu(
menuItem(text = "Population Filter",
uiOutput("choose_age")
)
)
),
dashboardBody(
tableOutput("smoke")
)
)
server <- function(input, output, session) {
output$choose_age <- renderUI({
selectInput("selected_age", "Age", with_demo_vars$age)
})
myData <- reactive({
with_demo_vars %>%
dplyr::filter(age == input$selected_age)
})
output$smoke <- renderTable({
req(input$selected_age)
head(myData())
})
}
shinyApp(ui = ui, server = server)
I need to be able to add another trace to a plot after a mouse click. I am using R's web framework Shiny to display the plot in a web browser. The series I want to add is dots or any series at this point.
I need to draw lines on the plot also. I want to click a starting point and a ending and a line pass through the clicked points.
This is what I have so far.
#############To Update
#if (!require("devtools"))
#install.packages("devtools")
#devtools::install_github("jbkunst/highcharter")
library("shiny")
library("highcharter")
dots<-hc_add_series_scatter(cars$speed, cars$dist)
hc_base <- highchart() %>%
hc_xAxis(categories = citytemp$month) %>%
hc_add_series(name = "Tokyo", data = citytemp$tokyo)
ui <- fluidPage(
h2("Viewer"),
fluidRow(
h3(""), highchartOutput("hc_1", width = "100%", height = "800px"),
h3("Click"), verbatimTextOutput("hc_1_input2")
)
)
server = function(input, output) {
output$hc_1 <- renderHighchart({
hc_base %>%
hc_add_theme(hc_theme_ffx())%>%
hc_tooltip(backgroundColor="skyblue",crosshairs = TRUE, borderWidth = 5, valueDecimals=2)%>%
hc_add_event_series(series="dots", event = "click")
})
output$hc_1_input2 <- renderPrint({input$hc_1_click })
}
shinyApp(ui = ui, server = server)
Any help would be greatly appreciated.
This could be one way of doing it:
library(shiny)
library(highcharter)
hc_base <- highchart() %>%
hc_xAxis(categories = citytemp$month) %>%
hc_add_series(name = "Tokyo", data = citytemp$tokyo)
ui <- fluidPage(
h2("Viewer"),
fluidRow(
h3(""), highchartOutput("hc_1", width = "100%", height = "800px"),
h3("Click"), verbatimTextOutput("hc_1_input2")
)
)
server = function(input, output) {
output$hc_1 <- renderHighchart({
hc_base %>%
hc_add_theme(hc_theme_ffx())%>%
hc_tooltip(backgroundColor="skyblue",crosshairs = TRUE, borderWidth = 5, valueDecimals=2)%>%
hc_add_event_point(event = "click")
})
observeEvent(input$hc_1_click,{
output$hc_1 <- renderHighchart({
hc_base %>%
hc_add_theme(hc_theme_ffx())%>%
hc_tooltip(backgroundColor="skyblue",crosshairs = TRUE, borderWidth = 5, valueDecimals=2)%>%
hc_add_series_scatter(cars$speed, cars$dist)
})
})
output$hc_1_input2 <- renderPrint({input$hc_1_click })
}
shinyApp(ui = ui, server = server)
Hope it helps!