Shiny App not responding - r

I have written a well functioning Shiny App, and I want to rewrite the code a little bit, to make it more elegant.
My probem: the App is loading for ages, and when it loads, it does not respond anymore. Strange thing that it is functioning well in the old version of the App.
This is what I have right now (after removing nearly everything):
ui.R:
library(shiny)
function(request){shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
),
mainPanel(
DT::dataTableOutput("table")
)
)
))}
server.R:
library(shiny)
library(DT)
library(crosstalk)
library(tidyverse)
data <- readRDS("report_summary2.rds")
shinyServer(function(input, output, session) {
computeTable <- function(){data %>% select("Year", "Month", "Date", "Transaction")}
output$table <- DT::renderDataTable({
DT::datatable(
data = computeTable(),
filter = "top",
rownames = FALSE,
options = list(
pageLength = 100
)
)
})
})
Unfortunately I cannot share report_summary.rds, as it contains sensitive information, it has like 500.000 rows and 9 columns in total, so dealing with that should not be the issue.
This was working in the old App version like a charm, but now it loads forever, and if I try to use the filters for dataTable (at the top), the App is not responding anymore.
I've been searching and looking, but could not find anything. Possibly anybody sees something?

You are right after > 400 thousand rows DT becomes slow being a single process (as well as Basic Shiny).
Here are some options:
To store and access data in RDBMS or noSQL.
Use Shiny Pro, which allows to split the load through multiple servers\applications.
Check as well architecture of your application (too much reactivity will slow it down).
And of course run a Profiler to find out where are your real bottle-necks. All other options are
somehow cosmetic: usage of global.R, split data table for
quick\small and bigger\slow parts etc.

Related

Is it possible to "Pre-render" a collapsibletree Shiny object with ~4000 nodes for end users?

I'm developing a shinyapp that involves displaying the company's managerial hierarchy.
Once uploaded to a remote server, it takes approximately 10-15 minutes for the app to completely render and become interactive for the end user.
Is it possible to keep the app "loaded" on the remote server so that end users have a significantly reduced load time?
My own searching suggests the solution is to keep renderCollapsibleTree in global.R and have the server run a session continuously (still need to figure out how to do that).
If there is a simpler solution, I'd love to hear it.
Edit: I've included my global.R code:
tree_data <- read.csv("FileName", header = TRUE, row.names = NULL, stringsAsFactors = FALSE) %>%
select(EmployeeName, SupervisorName, pathString)
hierarchy_tree <- data.tree::as.Node(tree_data, pathDelimiter = "/")
rendered.tree <- renderCollapsibleTree({
collapsibleTree(hierarchy_tree, inputId = "node")
})
and relevant part in my server.R code:
server <- function(input,output){
output$tree <- rendered.tree
}

rpivotTable: remove unnecessary aggregators

I create a interactive pivot table by using rpivotTable package. However, I found that some of aggregators and renderName are unnecessary for my users. I would like to remove them. For example, I want to remove "Average" from aggregator dropdown menu.
Here is my example:
library(shiny)
library(rpivotTable)
df <- iris
ui <- fluidPage(
fluidRow(
column(width=10, rpivotTableOutput("pivot"))
)
)
server <- function(input, output, session) {
output$pivot<-renderRpivotTable({
rpivotTable(df,
rendererName="Heatmap",
cols=c("Species"),
rows=c("Petal.Width"),
aggregatorName="Count",
hiddenFromAggregators=["Average"]
)
})
}
shinyApp(ui = ui, server = server)
I noticed that there seems some relevant parameters called "hiddenFromAggregators" but I cannot figure out how to apply it in R/Shiny environment.
Here is where I found "hiddenFromAggregators".
https://github.com/nicolaskruchten/pivottable/wiki/Parameters
You may be looking for something like this :
rpivotTable(iris,
rendererName = "Treemap",
cols = c("Species"),
rows = c("Petal.Width"),
aggregatorName = "Count",
aggregators = list(Sum = htmlwidgets::JS('$.pivotUtilities.aggregators["Sum"]'),
Count = htmlwidgets::JS('$.pivotUtilities.aggregators["Count"]')),
subtotals = TRUE)
There is probably a faster way than adding aggregators one by one (using full pivotUtilities.aggregators)
I couldn't find a full list of the default aggregators but you can get it with web inspector on your app (with Google Chrome: right click > inspect) and typing $.pivotUtilities.aggregators in the console tab.
The hiddenFromAggregators parameter affects which dataset attributes are eligible to be used as arguments to aggregators, rather than which aggregators are available. It is rather challenging in rpivotTable to pass in a custom set of aggregators but might be possible using something similar to the approach here: https://github.com/smartinsightsfromdata/rpivotTable/issues/81
You will need to familiarize yourself with the documentation here first: https://github.com/nicolaskruchten/pivottable/wiki/Aggregators

shiny DT _row_last_clicked

I am having an issue with the _row_last_clicked option provided for tables created in shiny interfaces with the rstudio DT library. I am trying to select a row in a datatable, make modifications to it and output it to the shiny ui.r. It works for the first-time selection, but when I again click on the same table row which I just selected previously, the _row_last_clicked seems to remain unresponsive (=NULL?). Here is a mininmal example (ui.r likely irrelevant) of what I am trying to achieve:
# server.r-side:
table_x<-# ... loads the dataframe
redo_cal<-reactiveValues()
redo_cal$a<-1
observe({
redo_cal$a
output$some_table <- DT::renderDataTable(
table_x,
server = TRUE, # same problem with FALSE
selection =c('single')
)
})
observeEvent(
input$some_table_row_last_clicked,{
s<-input$some_table_row_last_clicked
table_x[s,]<- # some reversible modifications based on the row selection ...
redo_cal$a<-(redo_cal$a+1) # trigger above renderDataTable
})
The issue persists for both the latest github version of DT as well as the release found on CRAN. I have read several related posts but couldn`t figure out a satisfying solution. Thank you very much for your help!
If i understand you right you need some_table_row_selected
and table_x(dd$d - in my example) be reactiveValues
See example where
# some reversible modifications based on the row selection == log of x
Every time you select row value of x in this row log-ed
library(shiny)
library(DT)
data=data.frame(x=1:10,y=2:11)
ui=shinyUI(
fluidPage(
DT::dataTableOutput("tt")
)
)
server=shinyServer(function(input, output) {
dd=reactiveValues(d=data)
output$tt=DT::renderDataTable(
datatable(
dd$d,selection =c('single')
)
)
observeEvent(input$tt_rows_selected,{
dd$d[input$tt_rows_selected,1]<-log(dd$d[input$tt_rows_selected,1])
})
})
shinyApp(ui,server)
In each session your data refreshed
PS
Best minimal example its something which anyone can copy\paste and test.

R Shiny app progress Indicator for loading data

Shiny is our internal BI tool. For our Shiny apps, we load data before shinyServer running:
load("afterProcessedData.RData")
# or dt = fread("afterProcessedData.csv")
shinyServer(function(input, output, session){ ...
However, some of apps are loading big files and they take up to 30s to load up. Many users, when they open a page, don't know whether the page is broken since it is stuck when it is loading. They may close it or click filters, which may cause an error. In this case, a progress bar will be very helpful. I notice withProgress() may help but it has to be inside reactive() or renderXx().
One way I can do is to have laod() warpped with reactive() inside the shinyServer(function(input, output, session){ but my concern is it will slower the performance. And my users very care about the responsive performance.
Any suggestions for this situation?
Edit: I guess there is not an easy way to do this. I have another thought. Maybe I can show a text on the screen saying 'the data is loading', but I have to make it disappear after the first table gets show up. However, I don't know how to set up the condition. Below is my code showing first table:
dashboardBody(
fluidRow(
tabBox(width = 12,
tabPanel("Summary",
dataTableOutput("data1")),
Thank you in advance!
Even though I am still interested in knowing how to add process bar for load(), I have implemented the alternative solution, which is good for now. It has a text saying 'the data is loading...' on the page, and it will disappear after first table shows up.
#server.R firstData is a reactive function to get the data for 1st table
output$firstTable = reactive({
return(is.null(firstData()))
})
#ui.R
conditionalPanel(
condition = "output.firstTable",
box(width = 12,
h1("The data is loading...")
)
)
To reference the intriguing note from #user5249203 , withSpinner() looks to be a useful option for this functionality and is a part of the shinycssloaders package. I have not used myself, but it is definitely an intriguing package that happens to be on CRAN and to have some nice examples: https://andrewsali.shinyapps.io/example/

gvisTables not rendering in Shiny apps

The actual issue I'm trying to solve: I'm creating a dashboard which will include data tables. I would like for numbers to be formatted with commas as thousands separators, but there is (apparently) an issue with the DT package when it's used with Shiny, in that the comma-separated formatting causes DT::renderDataTable to read in numbers as character, which affects how the numbers are sorted. (DT's number formatting functionality does not work with Shiny, it appears.)
Where I'm at so far: The only solution I've been able to find is to use googleVis instead of DT to create the tables. Now I'm running into a different issue (described below), but what I really care about is having data tables with comma-separated numbers that sort like numbers.
The GoogleVis issue: When I use gvisTable outside of Shiny apps, they render perfectly fine, but they do not render at all when using renderGvis and htmlOutput in Shiny. As an example, I'll borrow Example 4 from here.
Not using Shiny, my code looks like this:
library(datasets)
library(googleVis)
myOptions <- list(page='enable', pageSize=10, width=550)
Table <- gvisTable(Population,options=myOptions)
plot(Table)
Using Shiny, it's like this:
library(datasets)
library(googleVis)
library(shiny)
shinyApp(
ui = pageWithSidebar(
headerPanel("Example 4: pageable table"),
sidebarPanel(
checkboxInput(inputId = "pageable", label = "Pageable"),
conditionalPanel("input.pageable==true",
numericInput(inputId = "pagesize",
label = "Countries per page",10))
),
mainPanel(
htmlOutput("myTable")
)
),
server = function(input,output){
myOptions <- reactive({
list(
page=ifelse(input$pageable==TRUE,'enable','disable'),
pageSize=input$pagesize,
width=550
)
})
output$myTable <- renderGvis({
gvisTable(Population,options=myOptions())
})
}
)
Any help is much appreciated!
I solved my own problem. It turns out that RStudio's native browser has difficulty displaying googleVis exhibits through Shiny. All I needed to do was open it up in Firefox... I don't think I've ever felt so much "woot" and "ugh" at the same time before.

Resources