Slow grep() within shiny program - r

I have built a shiny application which is located at the URL below.
https://hdoran.shinyapps.io/openAnalysis/
On the tab called "Choose CrossFit Open Data" I have a textInput() function that calls a function that uses grep(), which is used to find names in a data frame.
The first time the program loads and a name is entered, the search seemingly occurs quickly and names are returned. However, when I delete the name and type a second name, the search is seemingly very slow.
Is there something I can do to optimize this so that is performs quickly always?
I'm still quite new at shiny and am not sure if somehow making this a reactive expression would help. If so, I'm not quite sure how.
Thanks in advance.
The relevant portion of code in the ui.R file
textInput("name", label = 'Enter an athlete name and find your scores',
value = "Enter Name Here")
and the relevant portion of code in the server.R file is
output$myScores <- renderPrint({
df <- filedata()
df[grep(input$name, df$Competitor),]
})
And this portion is also in the ui.R file (though I'm not sure it is relevant to the problem)
verbatimTextOutput("myScores"),

If I understand your goal correctly, you want to give the user the ability to select an input variable based on searching a the competitor column of the dataframe called by filedata()? If so, selectizeInput() is what you are looking for, using server-side selection as outlined here.
Adapted to the code you provided:
ui.r
selectizeInput("name", choices = NULL, multiple = FALSE)
server.r
updateSelectizeInput(session, "name", choices = filedata()$competitor, server = TRUE)
output$myScores <- renderPrint({
df <- filedata()
subset(df, competitor==input$name)
})

Related

Using reactiveFileReader in Shiny app to update a dataframe upon change to underlying CSV

I'm working on a complex (for me) Shiny app ~2500 lines of code. The basic structure is as follows, though I can't necessarily share a reproducible example since most of the information is confidential.
Right now, I am using df1 <- read.csv() etc to read in several CSV files as dataframes. I want to use reactiveFileReader() to make it such that the dataframes automatically update when the source CSV file is modified. I think my problem may be related to the fact that I am not doing this in a reactive context, but there is a reason for this. I am using the dataframes df1 etc to perform many calculations and to create new variables throughout the app (UI and server sections).
It also might be important to note that I am doing these file imports in the UI part of the Shiny app, since I need to rely on the factor levels of these dataframes to populate drop down selectInput in my UI. This might not be necessary.
Here is what I have tried (although I am pretty lost):
reader <- reactiveFileReader(intervalMillis = 1000, filePath =
"Data_Record.csv", readFunc = read.csv)
data_record <- reactive({
data_df <- reader()
return(data_df)
})
What I was expecting was for data_record to be a dataframe containing the information from the CSV, but it ends up being a "reactive expression". When I try to perform operations on data_record, like subsetting, I receive errors since that variable is not a dataframe.
Is there any way for me to update these dataframes upon modification to the underlying CSV outside of a reactive context? Even a scheduled update like every 10 seconds or so would work as well. My ultimate goal are dataframes that update when a CSV is modified, but scheduled updates are fine as well.
Thanks in advance for all the help and I apologize for not being able to supply a reproducible example! I will try to add more information as needed.
So if you want the data to be reactive, it has to be imported in the server section of the app as a 'reactive'. In shiny, 'reactives' become functions so to do anything with them you have to reference them their name followed by parenthesis inside a reactive function (reactive, observe, render etc).
For example, with your code above, reader becomes a reactive data frame. You can perform normal data manipulation on reader if you follow the rules of reactives outlined above.
# server.R
reader <- reactiveFileReader(intervalMillis = 1000, filePath =
"Data_Record.csv", readFunc = read.csv)
filtered_reader_df <- reactive({
reader() %>% filter(x > 100)
})
Where filtered_reader_df becomes a reactive filtered version of the reactive csv file. Again, to use filtered_reader_df in subsequent reactive function it must be referenced as filtered_reader_df() as it is a reactive function itself.
Finally, you can still use the reactive csv file to populate UI elements with the updateSelectInput() function inside an observer in the server. For example:
ui <- fluidPage(
selectInput("mySelectInput", "Select")
)
server <- function(input, output, session) {
reader <- reactiveFileReader(intervalMillis = 1000, filePath =
"Data_Record.csv", readFunc = read.csv)
observe({
select_input_choices <- unique(reader()$factor_column)
updateSelectInput(session, inputId = "mySelectInput", choices = select_input_choices)
})
}
The code above will update the choices of the select input every time the reader() data frame changes with the reactiveFileReader where unique(reader()$factor_column) are the reactive unique values of the factor column you want to populate the input with.

Creating a responsive actionButton for the user selcted checkboxes generated on the fly using dynamicUI [shiny/R]

I am stuck in a small problem related to shiny/R.
I am reading in a text file and displaying selective column names returned by grep search into the shiny application on the fly. For this, I am using the dynamicUI.
After the file is read in, the following function runs in server.R. It checks for specific colnames and displays this on the UI using uiOutput. Whatever column names are selected by the user, they are sent to another function for data processing and the plot it returned on the mainPanel.
server.R
output$Bait <- renderUI({
data <- input.data();
if(is.null(data)) return()
colnames <- names(data)
colnames = colnames[grep("*LFQ*",colnames,ignore.case=TRUE)]
# Creating the checkboxes using the above colnames
checkboxGroupInput("bait", "Choose Bait LFQ columns",
choices = colnames,
selected = colnames)
})
ui.R
shinyUI(
sidebarPanel(
uiOutput("Bait"),
),
mainPanel(
plotOutput(outputId = 'plot'),
)
)
Everything is fine, what I am trying to create is an action button for the checkboxes. Some files are big and have a longer list of column names >60, so whenever a checkbox is clicked, the whole function runs for processing and displays a plot. This gets unnecessary when the user has to deselect/select more than 10 columns.
An easy fix is, I kept selected=NULL but what I want is to add an actionButton after the checkboxGroupInput, so that user can select as many as checkBoxes but the function only runs when the GO button is pressed via the actionButton. If add a actionButton control after the checkbocGroupInput, it doesnt' works.
Can someone guide me in this regard. After working on this for sometime, now I am bit lost.
Thanks
Did you look into ?isolate? Lets say i want function initialFunction() only be evaluated if input$actionButtonis clicked.
observe({
input$actionButton # everything that triggers initialFunction() should come before isolate()
isolate({
# everything that should not trigger initialFunction() should come inside isolate()
initialFunction()
})
})

Passing R Shiny reactive SelectInput value to selectizeInput

My Shiny app uses open data from a bird atlas, including lat/lon coordinates by species. The bird species names come in different languages, plus as an acronym.
The idea is that the user first selects the language (or acronym). Based on the selection, Shiny renders a selectizeInput list of unique bird species names. Then, when one species is selected, a leaflet map is generated.
I've done a couple of Shiny apps but this time I miss something obvious. When the app starts, all is well. But, the selectizeInput list is not re-rendered when a new language is selected.
All the present code with some sample data is here as a GitHub Gist https://gist.github.com/tts/924b764e7607db5d0a57
If somebody could point to my problem, I'd be grateful.
The problem is that both the renderUI and the birds reactive blocks are dependent on the input$lan input.
If you add print(input$birds) in the birds block, you will see that it uses the name of the birds before renderUI has a chance to update them to fit the new language. The data you then pass the leaflet plot is empty.
Try adding isolate around input$lan in the birds expressions so that it is only dependent on input$birds:
birds <- reactive({
if( is.null(input$birds) )
return()
data[data[[isolate(input$lan)]] == input$birds, c("lon", "lat", "color")]
})
When you change the language, the renderUI will change the selectize, which will trigger the input$birds and update the data.
Instead of using renderUI, you could also create the selectizeInput in your ui.R using (replacing the uiOutput):
selectizeInput(
inputId = "birds",
label = "Select species",
multiple = F,
choices = unique(data[["englanti"]])
)
And in your server.R, update it using:
observe({
updateSelectizeInput(session, 'birds', choices = unique(data[[input$lan]]))
})

Shiny App : getting input choices from an uploaded file

I'm trying to use Shiny to get data from a file and use this data to populate a list.
The process is pretty standard. On a server.R file, I get a vector called 'list' by reading a csv file. I want to be able to select the value from this vector with a selectInput() function. So I put an observe loop to check if the file is uploded, and if it's correct, list is created.
observe({
inFile<-input$DATA
if(!is.null(inFile)){
data = read.table(inFile$datapath, header=T,sep=";")
list=unique(data$SLE)
}else{
list=NULL
}
})
My selectInput() is like this :
output$SLE = renderUI({ selectInput('SLE1', label='Choose the item :', levels(list)) })
If I put the selectinput() in the observe loop, the select box works well, except that every time the observe loop is executed, the selectbox is reset. So, it's not a solution.
If I leave the select box out of the observe loop, list keeps the defaut value even if the data file is loaded.
I've tried to set list as a reactive value but it wasn't a success. How can I set list?
You can have the select input inside a conditional panel in UI.R itself and
use a function in place of "choices=" to retrieve the data frame as the list of choices.
One example is as below:
in ui.R:
selectInput("id", "Select Employee:", get.Employee())
Required funcion:
get.Customers <- function(input){
# YOU CAN ENTER YOUR CODE IN HERE
df_input <- input$nr
return(df_input)
}

Shiny - Taking Text input into auxiliary function

I am new to Shiny and trying to build a more accessible input and output for a function I built. I am giving this to people that don't run R so trying to build something that runs my functions in the background and then spits out the answer.
I am having some trouble getting everything in the way that I want it unfortunately and dealing with a bunch of errors. However, here is my more pointed question:
The actual function that I want to run takes a name (in quotations as "Last,First") and a number.
PredH("Last,First",650)
So I want a shiny application that takes a name input and a number input that then runs this program and then spits back out a data table with my answer. So a couple of questions.
How do I get it in the right form to input into my equation on the server side script, do I need to return it in the function so it can be accessed using a function$table type access? (Right now I am just printing using cat() function in the console for the function but know that may not be usable for this type of application.
I want to return a dataframe that can be gotten at PredH14$table. How do I go about building that shiny?
Here is my code so far:
UI:
library(shiny)
shinyUI(pageWithSidebar(
# Application title
headerPanel("Miles Per Gallon"),
# Sidebar with controls to select the variable to plot against mpg
# and to specify whether outliers should be included
sidebarPanel(
textInput("playername", "Player Name (Last,First):", "Patch,Trevor"),
radioButtons("type", "Type:",
list("Pitcher" = "P",
"Hitter" = "H"
)),
numericInput("PAIP", "PA/IP:", 550),
submitButton("Run Comparables")
),
mainPanel(
textOutput("name")
)
Server:
library(shiny)
shinyServer(function(input, output) {
sliderValues <- reactive({
data.frame(
Name = c("name", "PA"),
Value = c(as.character(playername),
PAIP),
stringsAsFactors=FALSE)
})
name=input[1,2]
PAIP=input[2,2]
testing <- function(name,PAIP){
a=paste(name,PAIP)
return(a) }
output$name=renderText(testing$a)
})
I am not quite sure I understood your question 100% but I clearly see you are wondering how to pass the input of the UI into the server and maybe, the other way back.
In your server code, clearly you are not getting any input from the UI. Basically you have created three input variables in your ui.R:
1. input$playername
2. input$type
3. input$PAIP
And one output:
1. output$name
Just let you know, the function sliderValues <- reactive(..) is called every time there is any input from the input... like people click the dropdown list or people modifies words in the text box.
You can even get started without the submit button just to get started. But the existence of the submit button actually makes everything easier. Create a submit button for an input form. Forms that include a submit button do not automatically update their outputs when inputs change, rather they wait until the user explicitly clicks the submit button.
So you can put your code in a way similar like this:
# server.R
library(shiny)
shinyServer(function(input, output) {
sliderValues <- reactive({
result <- ... input$playername ... input$type ... input$PAIP
return(result)
})
output$name <- renderPlot/renderText (... sliderValues...)
})
# ui.R
library(shiny)
shinyUI(pageWithSidebar(
headerPanel("Miles Per Gallon"),
sidebarPanel(
textInput("playername" ... ),
radioButtons("type" ... ),
numericInput("PAIP" ... ),
submitButton("...")
),
mainPanel(
textOutput/plotOutput...("name")
)
))
In the end, check out the shiny example that might be what you want.
library(shiny)
runExample('07_widgets')

Resources