I use shiny modules to update a large number of value boxes.
The annoying part is the value boxes donot seem to scale above 10 or 20 as their updating is causing annoying flickers.
Even those boxes whose values are not changing on the next invalidation, flicker. Ideally if the value is not changing the box should not refresh.
A representative shiny app using shiny modules is presented to replicate the problem.
When the value of N is 4 or 5 the number of boxes are small and the updates happen instantaneously. As you increase N to 10 it gets noticeable and at N = 20 the flicker is unbearable.
### ui.R
## reprex ui.r
suppressPackageStartupMessages(library(shiny))
suppressPackageStartupMessages(library(magrittr))
suppressPackageStartupMessages(library(shinydashboard))
suppressPackageStartupMessages(library(shinydashboardPlus))
suppressPackageStartupMessages(library(lubridate))
suppressPackageStartupMessages(library(shinyjs))
ui <- dashboardPage(
header = dashboardHeader(title = "Reprex"),
sidebar = dashboardSidebar(
sidebarMenu(id = "sidebar",
menuItem(text = "Fuel prediction",tabName = "LIVE",icon = icon("tachometer-alt"))
)
), # end of sidebarMenu
body = dashboardBody(id="body",useShinyjs(),
tabItems(
tabItem(tabName = "LIVE",h1("FUEL DISPENSATION"),
fluidRow(id = "parameters",
column(width = 2,h3("STATION")),
column(width = 2,h4("TIME UPDT")),
column(width = 2,h4("TANK LEVEL")),
column(width = 2,h4("DISPENSED")),
column(width = 2,h4("REFUELLED"))
),
uiOutput("st1"),
uiOutput("st2"),
uiOutput("st3"),
uiOutput("st4"),
uiOutput("st5"),
uiOutput("st6"),
uiOutput("st7"),
uiOutput("st8"),
uiOutput("st9"),
uiOutput("st10"),
uiOutput("st11"),
uiOutput("st12"),
uiOutput("st13"),
uiOutput("st14"),
uiOutput("st15"),
uiOutput("st16"),
uiOutput("st17"),
uiOutput("st18"),
uiOutput("st19"),
uiOutput("st20")
)
)
) # End of body
) # end of dashboard page
And this is the server.R:
## reprex server.R
suppressPackageStartupMessages(library(shiny))
suppressPackageStartupMessages(library(shinydashboard))
suppressPackageStartupMessages(library(data.table))
source("modules.R")
shinyServer(function(input, output,session) {
seqno <- reactiveVal(5)
timer <- reactiveTimer(3000)
observeEvent(timer(),{
seqno((seqno() + 1))
for(i in seq_len(N)){ ## the for loop generates all the output assignment statements using shiny module.
genrVB(i = i,output = output,s = seqno())
}
})
# This is just to stop the app when session ends. Ignore for the purposes of this reprex.
session$onSessionEnded(function() {
print("Session ended")
stopApp()
})
})
And this is the modules.R
### Shiny module reprex
library(shiny)
library(purrr)
library(maps)
# take N cities and N data.tables randomly generated to serve our input data for the shiny app
N <- 4
cities <- world.cities %>% as.data.table() %>% .$name %>% sample(N)
### Generate N simulated data.tables for the N cities.
### Notice the values of the column 2,3,4 donot change every minute.
simdata <- purrr::map(seq_len(N),
~data.table(ts = seq.POSIXt(Sys.time(),by = 60,length.out = 100),
fuel = rep(c(5000:5004),each = 2),
out = rep(c(100,110),each = 25),
fill = rep(c(100,200),each = 10)
))
fuelrowUI <- function(id,label = "Site X",n = 1){
ns <- NS(id)
fluidRow(id = ns("siteid"),
column(2,h3(cities[n])),
valueBoxOutput(ns("upd"),width = 2),
valueBoxOutput(ns("tank"),width = 2),
valueBoxOutput(ns("out"),width = 2),
valueBoxOutput(ns("fill"),width = 2)
)
}
fuelrowServer <- function(id,datarow=1,n = 1){
moduleServer(id,
function(input,output,session){
output$upd <- renderValueBox(vbtime(n,k = datarow))
output$tank <- renderValueBox(vblevel(n,k = datarow))
output$out <- renderValueBox(vbout(n,k = datarow))
output$fill <- renderValueBox(vbin(n,k = datarow))
})
}
# Function to loop through the output$.. in server.R using the two shiny modules
genrVB <- function(i,s,output = output){
stn <- paste0("st",i)
output[[stn]] <- renderUI(fuelrowUI(stn,label = "DUMMY",n = i))
fuelrowServer(stn,datarow = s,n = i)
}
##### Value box helper functions ##########
vblevel <- function(n = 1,k=1){
val <- simdata[[n]][k,round(fuel,0)]
valueBox(value = paste(val,"L"),
subtitle = tags$h4(cities[n]),
color = case_when(
val < 1000 ~ "red",
val >= 1000 ~ "green"
))
}
vbout <- function(n = 1,k=1){
val = simdata[[n]][k,out]
valueBox(value = paste(val,"L"),
subtitle = tags$h4(cities[n]),
color = case_when(
val < 100 ~ "aqua",
val >= 100 ~ "purple"
))
}
vbin <- function(n = 1,k=1){
val = simdata[[n]][k,fill]
valueBox(value = paste(val,"L"),
subtitle = tags$h4(cities[n]),
color = case_when(
val < 100 ~ "teal",
val >= 100 ~ "olive"
))
}
# Time Value box
vbtime <- function(n = 1,k = 1){
time <-simdata[[n]][k,ts]
timestr <- format(time,"%H:%M")
valueBox(value = timestr,
subtitle = "Last Updated",color = "aqua")
}
Please load the three code sections in three files: ui.R, server.R and modules.R.
Note: In the modules.R the first line has a line N <- 4. Please set it to 20 to see the annoying flicker.
If you only want to stop the flashing while recalculating all you'll have to do is adding
tags$style(".recalculating { opacity: inherit !important; }")
to your UI - taken from here.
Still I'd encourage you to simplify your app for better performance.
Here is an example for the approach I mentioned in the comments:
library(shiny)
library(shinydashboard)
library(data.table)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody(
tags$style(".recalculating { opacity: inherit !important; }"),
fluidPage(
sliderInput(
inputId = "nBoxesRows",
label = "rows of Boxes",
min = 1L,
max = 100L,
value = 20L
),
uiOutput("myValueBoxes")
)
)
)
server <- function(input, output, session) {
DT <- reactive({
invalidateLater(1000)
data.table(replicate(4, round(runif(input$nBoxesRows), digits = 2)))
})
output$myValueBoxes <- renderUI({
longDT <- melt(DT(), measure.vars = names(DT()))
longDT[, subtitle := paste0(variable, "_", seq_len(.N)), by = variable]
tagList(mapply(valueBox, subtitle = longDT$subtitle, value = longDT$value, MoreArgs = list(width = 3), SIMPLIFY = FALSE))
})
}
shinyApp(ui, server)
Related
I am trying to plot some epidemiological data. To do this, I am using the shiny app (following the steps of this tutorial).
When I start the app, a further tab opens and i can see the graphs, a map and an input . When I change the date input on the app (using reactivity), the app crashes and all I see is a gray display. I am forced to exit RStudio. It is really strange, because I already did some tests using an older Macbook Pro (2,7 GHz Dual-Core Intel Core i5 Prozessor) and although it was slow, RStudio did not crash. Is it maybe something related to the Apple M1 chip?
library(shiny)
library(shinyWidgets)
library(rgdal)
library(DT)
library(dygraphs)
library(xts)
library(leaflet)
# ui object
ui <- fluidPage(
titlePanel(p("Spatial app", style = "color:#3474A7")),
sidebarLayout(
sidebarPanel(
selectInput(
inputId = "variableselected",
label = "Select variable",
choices = c("n", "Pop", "incidence_rate")
),
dateRangeInput('dateRange',label = "Pédiode d'analyse : ",format = "yyyy-mm-dd",
start = Sys.Date(), end=Sys.Date(),startview = "year",separator = " - "),
p("Made with", a("Shiny",
href = "http://shiny.rstudio.com"
), "."),
img(
src = "imageShiny.png",
width = "70px", height = "70px"
)
),
mainPanel(
leafletOutput(outputId = "map"),
dygraphOutput(outputId = "timetrend"),
DTOutput(outputId = "table")
)
)
)
# server()
server <- function(input, output) {
output$table <- renderDT(data)
output$timetrend <- renderDygraph({
dataxts <- NULL
counties <- unique(data$COD_MUN_N)
for (l in 1:length(counties)) {
datacounty <- data[data$COD_MUN_N == counties[l], ]
dd <- xts(
datacounty[, input$variableselected],
as.Date(paste0(datacounty$weekly_cases, "-01-01"))
)
dataxts <- cbind(dataxts, dd)
}
colnames(dataxts) <- counties
dygraph(dataxts) %>%
dyHighlight(highlightSeriesBackgroundAlpha = 0.2) -> d1
d1$x$css <- "
.dygraph-legend > span {display:none;}
.dygraph-legend > span.highlight { display: inline; }
"
d1
})
output$map <- renderLeaflet({
# Add data to map
datafiltered <- data[data$weekly_cases >= input$dateRange[1] & data$weekly_cases <= input$dateRange[2], ]
# this returns positions of map#data$NAME in datafiltered$county
ordercounties <- match(map#data$MPIO_CCDGO, datafiltered$COD_MUN_N)
map#data <- datafiltered[ordercounties, ]
map$variableplot <- as.numeric(
map#data[, input$variableselected]
)
# Create leaflet
pal <- colorBin("YlOrRd", domain = map$variableplot, bins = 7)
labels <- sprintf("%s: %g", map$COD_MUN_N, map$variableplot) %>%
lapply(htmltools::HTML)
l <- leaflet(map) %>%
addTiles() %>%
addPolygons(
fillColor = ~ pal(variableplot),
color = "white",
dashArray = "3",
fillOpacity = 0.7,
label = labels
) %>%
leaflet::addLegend(
pal = pal, values = ~variableplot,
opacity = 0.7, title = NULL
)
})
}
# shinyApp()
shinyApp(ui = ui, server = server)
I am working on an app where the user can upload either one file or multiple files of individual-level data to get analyzed.
So far if the user uploads multiple files the app combines all the files in one dataset and analyzes all of them combined. I have different outputs 2 tables and a graph.
What I am struggling to do is when the user uploads multiple files I want to keep the compiled result but I want to add dynamic tabs to each box according to the number of files uploaded to present the table/graph for that file alone.
I added a checkbox so the user checks it if they are uploading multiple files. The idea was to write an observeEvent code to insert tabs according to the number of files being uploaded, that code got complicated because I had to put the renderTable chunk within it, and it is not working.
So my question is, is there a better way of doing what I am trying to do? and If my idea makes sense what is wrong with my code and why isn't it working? Thank you
Here is a sample of the code;
library(shiny)
library(dplyr)
library(shinydashboard)
library(tidyr)
library(shinyjs)
ui <- dashboardPage(
dashboardHeader(title = "Treatment and Care Cascade",
titleWidth = 300),
#Sidebar contents (tabs)
dashboardSidebar(
sidebarMenu(
menuItem("HIV Cascade", tabName = "hiv")
)),
#Main panel for displaying outputs
dashboardBody(
tabItems(
#First tab content
tabItem(tabName = "hiv",
h2("HIV Treatment and Care Cascade"),
fluidRow(
#Input: Select a file for hcv data
box(fluidRow(
box(fileInput("dt_hiv","Choose CSV File",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,tesxt/plain",".csv")),width = 12,solidHeader = TRUE, height = 75),
#Input: Checkbox if file has header
box(checkboxInput("multiplehiv", "Uploading multiple files",TRUE),width = 3,solidHeader = TRUE, height = 50)), width = 12, height = 255),
#Outputs
tabBox(id = "hivcasbox", tabPanel(id = "tab1", title ="HIV Cascade",tableOutput("hivcascade"))),
box(tableOutput("hivCascadeduration"), title = "HIV Cascade - duration", solidHeader = TRUE)
))
)))
server <- function(input, output){
#Combining the datasets together
dthiv <- reactive({req(input$dt_hiv)
rbindlist(lapply(input$dt_hiv$datapath, fread, header = input$hivheader, quote = input$hivquote, sep = input$hivsep),
use.names = TRUE, fill = TRUE)
})
#The analysis chunk
cascade_hiv <- reactive({dthiv() %>% summarize("Diagnosed" = sum(hiv_posresult,na.rm = T),
"Linkage to care" = sum(linkagetocare_hiv,na.rm = T))})
cascade_hiv1 <- reactive({as.data.frame(t(cascade_hiv()))})
Percentage <- reactive({(round((cascade_hiv1()$V1*100/cascade_hiv1()$V1[1]),1))})
cascade_hiv3 <- reactive({cbind(cascade_hiv1(),Percentage())})
cascade_hiv4 <- reactive({cascade_hiv3() %>% rename(Total = V1, Percentage = "Percentage()")})
output$hivcascade <- renderTable({
cascade_hiv5 <- as.data.frame(cascade_hiv4())
rownames(cascade_hiv5) <- c("Diagnosed","Linkage to care")
cascade_hiv5},include.rownames = TRUE)
observeEvent(input$multiplehiv, {
for (i in 1:length(input$dt_hiv$datapath)) {
insertTab(inputId = "hivcasbox",
tabPanel(paste("Region",i), renderTable({
dthiv_r <- input$dt_hiv$datapath[i] %>% summarize("Diagnosed" = sum(hiv_posresult,na.rm = T),
"Linkage to care" = sum(linkagetocare_hiv,na.rm = T))
cascade_hiv1_r <- as.data.frame(t(dthiv_r))
Percentage_r <- round((cascade_hiv1_r$V1*100/cascade_hiv1_r$V1[1]),1)
cascade_hiv3_r <- cbind(cascade_hiv1_r,Percentage_r)
cascade_hiv4_r <- cascade_hiv3_r %>% rename(Total = V1, Percentage = "Percentage_r")
cascade_hiv5_r <- as.data.frame(cascade_hiv4_r)
rownames(cascade_hiv5_r) <- c("Diagnosed","Linkage to care")
cascade_hiv5_r},include.rownames = FALSE)),
target = "tab1")
}
})
}
shinyApp(ui, server)
Created on 2019-08-01 by the reprex package (v0.3.0)
the app runs but when I check the multiple files box, no tabs get inserted
I couldn't get the above code to work but I found another one that works using "str and eval(parse(text = str))",
however, it is not the most elegant or concise code, so I would appreciate it if someone has a better way of doing it. Thank you!
ibrary(shiny)
library(dplyr)
library(shinydashboard)
library(tidyr)
library(shinyjs)
library(data.table)
ui <- dashboardPage(
dashboardHeader(title = "Treatment and Care Cascade",
titleWidth = 300),
dashboardSidebar(
sidebarMenu(
menuItem("HIV Cascade", tabName = "hiv")
)),
dashboardBody(
tabItems(
#First tab content
tabItem(tabName = "hiv",
h2("HIV Treatment and Care Cascade"),
fluidRow(
#Input: Select a file for hcv data
box(fluidRow(
box(fileInput("dt_hiv","Choose CSV File",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,tesxt/plain", ".csv")),width = 12,solidHeader = TRUE, height = 75),
#actionButton("multiplehiv", "Add 'Dynamic' tab"),
#Input: Checkbox if file has header
box(checkboxInput("multiplehiv", "Uploading multiple files",FALSE),
width = 3,solidHeader = TRUE, height = 50)
), width = 12, height = 255),
#Outputs
uiOutput("tabs")
))
)))
server <- function(input, output){
dthiv <- reactive({req(input$dt_hiv)
rbindlist(lapply(input$dt_hiv$datapath, fread),
use.names = TRUE, fill = TRUE)
})
cascade_hiv <- reactive({dthiv() %>% summarize("Diagnosed" = sum(hiv_posresult,na.rm = T),
"Linkage to care" = sum(linkagetocare_hiv,na.rm = T))})
cascade_hiv1 <- reactive({as.data.frame(t(cascade_hiv()))})
Percentage <- reactive({(round((cascade_hiv1()$V1*100/cascade_hiv1()$V1[1]),1))})
cascade_hiv3 <- reactive({cbind(cascade_hiv1(),Percentage())})
cascade_hiv4 <- reactive({cascade_hiv3() %>% rename(Total = V1, Percentage = "Percentage()")})
n_files <- reactive({length(input$dt_hiv$datapath)})
output$tabs <- renderUI({
if (input$multiplehiv == 1) {
str <- "tabBox(id = 'hivcasbox',
tabPanel(id = 'taball', title = 'HIV Cascade' ,tableOutput('hivcascade')),"
for (i in 1:n_files()) {str <- paste0(str, "tabPanel(id = paste('tab', ",i,") , title = paste('Data', ",i,") , tableOutput('hivcascader_",i,"')),")}
str <- gsub(",$",")",str)
eval(parse(text = str))
}
else {
tabBox(id = "hivcasbox",
tabPanel(id = "tab1", title = "HIV Cascade",tableOutput("hivcascade")))
}
})
output$hivcascade <- renderTable({
cascade_hiv5 <- as.data.frame(cascade_hiv4())
rownames(cascade_hiv5) <- c("Diagnosed","Linkage to care")
cascade_hiv5},include.rownames = TRUE)
dt_files <- reactive({lapply(input$dt_hiv$datapath[1:n_files()],read.csv)})
observe({
for (i in 1:n_files())
{str1 <- paste0("dthiv_r_",i,"<- reactive({dt_files()[[",i,"]] %>% summarize('Diagnosed' = sum(hiv_posresult,na.rm = T),
'Linkage to care' = sum(linkagetocare_hiv,na.rm = T))})
cascade_hiv1_r_",i,"<- reactive({as.data.frame(t(dthiv_r_",i,"()))})
Percentage_r_",i,"<- reactive({round((cascade_hiv1_r_",i,"()$V1*100/cascade_hiv1_r_",i,"()$V1[1]),1)})
cascade_hiv3_r_",i," <- reactive({cbind(cascade_hiv1_r_",i,"(),Percentage_r_",i,"())})
cascade_hiv4_r_",i,"<- reactive({cascade_hiv3_r_",i,"() %>% rename(Total = V1, Percentage = 'Percentage_r_",i,"()')})")
eval(parse(text = str1))}
for (i in 1:n_files()) {
str2 <- paste0("output$hivcascader_",i," <- renderTable({
cascade_hiv5_r_",i," <- as.data.frame(cascade_hiv4_r_",i,"())
rownames(cascade_hiv5_r_",i,") <- c('Diagnosed','Linkage to care')
cascade_hiv5_r_",i,"},include.rownames = TRUE)")
eval(parse(text = str2))}
})
}
shinyApp(ui, server)
I am using googleway library in Shiny R.
The heatmap displays correctly, but I cannot change the heatmap options. If I uncomment the block code where I try to change options, the app crashes.
Here is the part of the code that works, with the offending lines commented out.
library(googleway)
library(magrittr)
library(shiny)
library(shinydashboard)
# Define UI for app
header1 <- dashboardHeader(
title = "My Dashboard"
)
sidebar1 <- dashboardSidebar(
sidebarMenu(
fileInput("file0", "Choose CSV File",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",".csv")),
sliderInput("opacity", "Opacity:",
min = 0, max = 1,
value = 0.5, step = 0.05),
sliderInput("radius", "Radius:",
min = 0, max = 50,
value = 25),
sliderInput("blur", "Blur:",
min = 0, max = 1,
value = 0.75, step = 0.05),
sliderInput("maxvalue", "MaxValue:",
min = 0, max = 1,
value = 1, step = 0.05)
) #sidebarMenu
) #dashboardSidebar
body1 <- dashboardBody(
fluidRow(
tabBox(
title = "TabBox Title 1",
id = "tabset1", height = "400px", width = 11,
selected = "Tab1",
tabPanel("Tab1",
google_mapOutput("Map1")
),
tabPanel("Tab2", "Tab content 2")
) #box
) #fluidRow
) #dashboardBody
ui <- dashboardPage(header1, sidebar1, body1)
# Define data
df <- data.frame(lat = c(14.61),
lon = c(-90.54),
weight = c(100))
# Define SERVER logic
server <- function(input, output, session) {
map_key <- "my_key"
## https://developers.google.com/maps/documentation/javascript/get-api-key
## plot the map
output$Map1 <- renderGoogle_map({
google_map(key = map_key, data = df, zoom = 2, search_box = F) %>%
add_heatmap(weight = "weight") #%>%
#add_traffic()
}) #renderGoogle_map
observeEvent(input$opacity, {
# THIS PART IS COMMENTED OUT BECAUSE THE APP CRASHES
# google_map_update(map_id = "Map1") %>%
# update_heatmap(data = df, option_opacity = input$opacity)
}) #observeEvent
} #server
# Run app
shinyApp(ui, server)
Your help with this will be greatly appreciated! :)
You can use a reactive({}) to carry the input$opacity value and pass it directly to add_heatmap() to achieve the opacity responsiveness.
This can still be done inside the google_map_update(), but you'd have to clear the heatmap layer first, otherwise you'd just be adding layers on top of each other.
server <- function(input, output, session) {
map_key <- "your_key"
## https://developers.google.com/maps/documentation/javascript/get-api-key
opacity <- reactive({
return(input$opacity)
})
## plot the map
output$Map1 <- renderGoogle_map({
google_map(key = map_key, data = df, zoom = 2, search_box = F) %>%
add_heatmap(weight = "weight") #%>%
#add_traffic()
}) #renderGoogle_map
observeEvent(input$opacity, {
google_map_update(map_id = "Map1") %>%
clear_heatmap() %>%
add_heatmap(data = df, option_opacity = opacity())
})
}
} #server
I am trying to create a shiny-app that load data-set, present the variable list and their classes and allow the user to modify the class of a selected variable. All the functions in the following code are working except to the last function in the server- observeEvent which not working when trying to modify the variable class. Any suggestions?
Thank you in advance,
Rami
`
rm(list = ls())
library(shiny)
library(shinydashboard)
library(DT)
ui <- dashboardPage(
dashboardHeader(title = "Shiny Example"),
#--------------------------------------------------------------------
dashboardSidebar(
sidebarMenu(
menuItem("Data", tabName = "data", icon = icon("th"))
)
),
#--------------------------------------------------------------------
dashboardBody(
#--------------------------------------------------------------------
tabItem(tabName = "data",
fluidPage(
fluidRow(
box(
selectInput('dataset', 'Select Dataset', list(GermanCredit = "GermanCredit",
cars = "cars",
iris = "iris")),
title = "Datasets",width = 4, status = "primary",
checkboxInput("select_all", "Select All Variable", value = TRUE),
conditionalPanel(condition = "input.select_all == false",
uiOutput("show.var"))
),
box(
title = "Variable Summary", width = 4, status = "primary",
DT::dataTableOutput('summary.data')
),
box(
title = "Modify the Variable Class", width = 4, status = "primary",
radioButtons("choose_class", label = "Modify the Variable Class",
choices = list(Numeric = "numeric", Factor = "factor",
Character = "character"),
selected = "numeric"),
actionButton("var_modify", "Modify")
)
)
)
)
)
)
#--------------------------------------------------------------------
# Server Function
#--------------------------------------------------------------------
server <- function(input, output,session) {
#--------------------------------------------------------------------
# loading the data
get.df <- reactive({
if(input$dataset == "GermanCredit"){
data("GermanCredit")
GermanCredit
}else if(input$dataset == "cars"){
data(cars)
cars
}else if(input$dataset == "iris"){
data("iris")
iris
}
})
# Getting the list of variable from the loaded dataset
var_list <- reactive(names(get.df()))
# Choosing the variable - checkbox option
output$show.var <- renderUI({
checkboxGroupInput('show_var', 'Select Variables', var_list(), selected = var_list())
})
# Setting the data frame based on the variable selction
df <- reactive({
if(input$select_all){
df <- get.df()
} else if(!input$select_all){
df <- get.df()[, input$show_var, drop = FALSE]
}
return(df)
})
# create list of variables
col.name <- reactive({
d <- data.frame(names(df()), sapply(df(),class))
names(d) <- c("Name", "Class")
return(d)
})
# render the variable list into table
output$summary.data <- DT::renderDataTable(col.name(), server = FALSE, rownames = FALSE,
selection = list(selected = 1, mode = 'single'),
options = list(lengthMenu = c(5, 10, 15, 20), pageLength = 20, dom = 'p'))
# storing the selected variable from the variables list table
table.sel <- reactive({
df()[,which(colnames(df()) == col.name()[input$summary.data_rows_selected,1])]
})
# Trying to modify the variable class
observeEvent(input$var_modify,{
modify.row <- which(colnames(df()) == col.name()[input$summary.data_rows_selected,1])
if( input$choose_class == "numeric"){
df()[, modify.row] <- as.numeric(df()[, modify.row])
} else if( input$choose_class == "factor"){
df()[, modify.row] <- as.factor(df()[, modify.row])
} else if( input$choose_class == "character"){
df()[, modify.row] <- as.character(df()[, modify.row])
}
})
}
shinyApp(ui = ui, server = server)
`
I would use reactiveValues() instead.
library(shiny)
# Define UI for application that draws a histogram
ui <- shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("classType", "Class Type:", c("as.numeric", "as.character"))
),
mainPanel(
textOutput("class")
)
)
))
server <- shinyServer(function(input, output) {
global <- reactiveValues(sample = 1:9)
observe({
global$sample <- get(input$classType)(global$sample)
})
output$class <- renderText({
print(class(global$sample))
})
})
shinyApp(ui = ui, server = server)
In case you are interested:
Concerning your attempt: reactive() is a function and you called the output of the function by df()[, modify.row]. So in your code you try to change the output of the function, but that does not change the output of futures calls of that function.
Maybe it is easier to see in a simplified version:
mean(1:3) <- 1
The code can not change the mean function to output 1 in future. So thats what reactiveValues() help with :). Hope that helps!
I am creating shiny app. My goal is to visualize some data slices depending on the input.I am quite happy with the result.
However, my app has a few bugs while the app is loading. Before ploting the graph and visualizing inputs it shows some errors on screen (you can lauch the app and see the problem).
I believe, the first problem is with data filtering. I can't figure out how to deal with it and what is the problem. May I need to use other method or maybe other package? (see the output$Brand).
Error in grep(pattern, levels(vector)) : invalid 'pattern' argument
The second error comes when I am creating selectInput. I'd like to visualize all the brands of the specific category in one plot and to have an option to filter data by brand. However, my method is not working well. Any suggestions? (see the output$Brand).
Error in if (input$Brand == "All") { : argument is of length zero
Also, I enclose the code, which you can generate.
May you have any more suggestions how to simplify the code?
Thanks for the help!
library(shiny)
library(shinydashboard)
library(data.table)
library(ggplot2)
library(grid)
library(scales)
library(ggthemes)
# Header -----------------------------------------------------------
header <- dashboardHeader(title="Dashboard")
# Sidebar --------------------------------------------------------------
sm <- sidebarMenu(
menuItem(
text="Graph1",
tabName="Graph1",
icon=icon("home")
)
)
sidebar <- dashboardSidebar(sm)
# Body --------------------------------------------------
body <- dashboardBody(
# Layout --------------------------------------------
tabItems(
tabItem(
tabName="Graph1",
fluidPage(
fluidRow(
box(
title = "Inputs", status = "warning", width = 2, solidHeader = TRUE,
uiOutput("Year"),
uiOutput("Category"),
uiOutput("Brand"),
sliderInput("Finalas.Range", "Months:",
min = 1, max = 12, value = c(1,12))
),
box(
title = "Season", width = 10, status = "info", solidHeader = TRUE,
plotOutput("Graph1")
)
)
)
)
)
)
# Setup Shiny app UI components -------------------------------------------
ui <- dashboardPage(header, sidebar, body, skin="black")
# Setup Shiny app back-end components -------------------------------------
server <- function(input, output) {
# Generate data --------------------------------------
set.seed(1992)
n=99
Year <- sample(2013:2015, n, replace = TRUE, prob = NULL)
Month <- sample(1:12, n, replace = TRUE, prob = NULL)
Category <- sample(c("Car", "Bus", "Bike"), n, replace = TRUE, prob = NULL)
Brand <- sample("Brand", n, replace = TRUE, prob = NULL)
Brand <- paste0(Brand, sample(1:14, n, replace = TRUE, prob = NULL))
USD <- abs(rnorm(n))*100
df <- data.frame(Year, Month, Category, Brand, USD)
# Inputs --------------------------------------
output$Year <- renderUI({
selectInput("Year",
"Year:",
c(unique(as.character(df$Year))), selected = "2015")
})
output$Category <- renderUI({
selectInput("Category", "Choose category:",
choices = c("Car","Bus", "Bike" ))
})
output$Brand <- renderUI({
df2 <- (data.table(df))[like(df$Category,input$Category)]
selectInput("Brand",
"Brand:",
c("All", unique(as.character(df2$Brand))))
})
# Plot --------------------------------
output$Graph1 <- renderPlot({
df <- data.table(df)
if (input$Brand == "All") {
df <- df[like(df$Year, input$Year)]
df <- df[like(df$Category,input$Category)]
ggplot(df, aes(x=factor(Month,levels=1:12), y=USD, fill=Brand))+
geom_bar(stat='identity')+
scale_x_discrete('Month', breaks=factor(1:12), drop=FALSE)+
scale_fill_gdocs(guide = guide_legend(title = "Brand"))
} else {
df <- df[like(df$Year, input$Year)]
df <- df[like(df$Category,input$Category)]
df <- df[which(df$Brand == input$Brand),]
validate(
need(sum(df$USD)>0, paste(input$Brand, "was inactive in Year:",input$Year))
)
ggplot(df, aes(x=factor(Month,levels=1:12), y=USD, fill=Brand))+
geom_bar(stat='identity')+
scale_x_discrete('Month', breaks=factor(1:12), drop=FALSE)
}
})
# -----------------------------------------------------------------------------
}
# Render Shiny app --------------------------------------------------------
shinyApp(ui, server)
The following should eliminate these errors: for #1 the function like in datatable gives out the error so I changed it to %in% instead. and for #2 you have a null as a default so take care of that with an if statement
rm(list = ls())
library(shiny)
library(shinydashboard)
library(data.table)
library(ggplot2)
library(grid)
library(scales)
library(ggthemes)
# Header -----------------------------------------------------------
header <- dashboardHeader(title="Dashboard")
# Sidebar --------------------------------------------------------------
sm <- sidebarMenu(
menuItem(
text="Graph1",
tabName="Graph1",
icon=icon("home")
)
)
sidebar <- dashboardSidebar(sm)
# Body --------------------------------------------------
body <- dashboardBody(
# Layout --------------------------------------------
tabItems(
tabItem(
tabName="Graph1",
fluidPage(
fluidRow(
box(
title = "Inputs", status = "warning", width = 2, solidHeader = TRUE,
uiOutput("Year"),
uiOutput("Category"),
uiOutput("Brand"),
sliderInput("Finalas.Range", "Months:",
min = 1, max = 12, value = c(1,12))
),
box(
title = "Season", width = 10, status = "info", solidHeader = TRUE,
plotOutput("Graph1")
)
)
)
)
)
)
# Setup Shiny app UI components -------------------------------------------
ui <- dashboardPage(header, sidebar, body, skin="black")
# Setup Shiny app back-end components -------------------------------------
server <- function(input, output) {
# Generate data --------------------------------------
set.seed(1992)
n=99
Year <- sample(2013:2015, n, replace = TRUE, prob = NULL)
Month <- sample(1:12, n, replace = TRUE, prob = NULL)
Category <- sample(c("Car", "Bus", "Bike"), n, replace = TRUE, prob = NULL)
Brand <- sample("Brand", n, replace = TRUE, prob = NULL)
Brand <- paste0(Brand, sample(1:14, n, replace = TRUE, prob = NULL))
USD <- abs(rnorm(n))*100
df <- data.frame(Year, Month, Category, Brand, USD)
# Inputs --------------------------------------
output$Year <- renderUI({
selectInput("Year",
"Year:",
c(unique(as.character(df$Year))), selected = "2015")
})
output$Category <- renderUI({
selectInput("Category", "Choose category:",
choices = c("Car","Bus", "Bike" ))
})
output$Brand <- renderUI({
# first error
#df2 <- (data.table(df))[like(df$Category,input$Category)]
df2 <- df[df$Category %in% input$Category,]
selectInput("Brand",
"Brand:",
c("All", unique(as.character(df2$Brand))))
})
# Plot --------------------------------
output$Graph1 <- renderPlot({
df <- data.table(df)
if(is.null(input$Brand) || is.na(input$Brand)){return()}
else if (input$Brand == "All") {
df <- df[like(df$Year, input$Year)]
df <- df[like(df$Category,input$Category)]
ggplot(df, aes(x=factor(Month,levels=1:12), y=USD, fill=Brand))+
geom_bar(stat='identity')+
scale_x_discrete('Month', breaks=factor(1:12), drop=FALSE)+
scale_fill_gdocs(guide = guide_legend(title = "Brand"))
} else {
df <- df[like(df$Year, input$Year)]
df <- df[like(df$Category,input$Category)]
df <- df[which(df$Brand == input$Brand),]
validate(
need(sum(df$USD)>0, paste(input$Brand, "was inactive in Year:",input$Year))
)
ggplot(df, aes(x=factor(Month,levels=1:12), y=USD, fill=Brand))+
geom_bar(stat='identity')+
scale_x_discrete('Month', breaks=factor(1:12), drop=FALSE)
}
})
# -----------------------------------------------------------------------------
}
# Render Shiny app --------------------------------------------------------
shinyApp(ui, server)