R shiny load data.frame for selectInput - r

I am trying to write a shiny app that loads several data frames. The data frames for my plots all work very well, but one data.frame which I want to use as a list of options in a dropdown menu does not load. If I load the frame seperately in the R session, everything works, but if I only run the shiny app, the selectors won't update.
library(shiny)
ui <- fluidPage(
#...
selectInput("mats", "Text",
selectors)
# ...
)
server <- function(input, output){
# ...
df1=read.csv("./data/file.csv", sep=";", head=T, stringsAsFactors = F)
df1$choices=as.character(df1$choices)
selectors=c("All", df1$choices)
#...
}
shinyApp(ui = ui, server = server)
I think, I need the selectors in the server function, so I loaded the data frame there together with my other data frames. Is that the right place and what do I need to do to get this running?
Best

There is a number of problems with your code:
Following the documentation, choices in selectInput should be a list.
If you want to create an element that would be available across the ui and server please consider reading the linked article on scoping rules in Shiny and defining your object in global.R.
With respect to the 1st point, if your intention is to use a data.frame column as a base for menu selection, you can apply the following transformation:
my_new_list <- split(df$id, df$subject)
as provided in this answer by #user3710546 to a similar question that I've asked in past.
Side note
Please consider having a look at the discussion on making a reproducible example in R. If you care to redo your example using some publicly available data, it will be easy to produce a solution. If I understood the problem correctly, you want to use data.frame column as a base for UI element, which is not difficult on its own.
.

Related

R: Data Frame launching manually works well, in shiny is incomplete

I webscraped 2 tables (A and B). Then I merge them by rows (rbind). When I launch it, everything is ok. When I wanna use it in shiny app there is something wrong. Below structure of tables and what shiny shows. Any suggestion? Where could be the problem? Unfortunatelly, I can not show the code, because this is for my thesis. I would be very grateful for your help.
As you can see the problem is with third column. B table has all rows with NA. After merge, all data from A table has also NA.
In shiny table is showed by renderTable.
Structure of tables A and B
I have no answer for your question, but I would like to write something and there is not enough space for this in comment section, so I will write this as answer and eventually delete later. So - I rather believe that there is something wrong with your code which you use inside shiny and would like to check this with your help. I assume you need some help with debugging, so I will post a code below:
library(shiny)
ui <- fluidPage(
tableOutput("table")
)
server <- function(input, output, session) {
my_df <- reactive({
data.frame(a = c(1, 2, 3),
b = c(4, 5, 6))
})
output$table <- renderTable({
my_df()
browser()
})
}
shinyApp(ui, server)
In the code above I have made one output (table output) and - on the server side in reactive - I'm creating data.frame. Then I use this reactive function inside my output (output$plot). However, the last line inside output$plot is function browser() which is used for debugging. You can try my code in your console and see that when you run shiny app, it immediately moving back to console (but this is "dubugging state", so console looks a little different, for example there is a button "stop" with red square which can be use to close debugging state). Please run my shiny app and when you will be back in the console, in the debugging state, type my_df() to see the data.frame object. Could you please do the same with your shiny app? I mean, could you use browser() function on the last line in your renderTable? And come back and tell if the last column contains only NA or not when displayed in the console? If not, then I would say that you are doing something different in Shiny than manually with your tables.

reactive object in UI using Shiny R

I have developed an app with Shiny R which can make some plots changing inputs (selecting the variables of a data frame).
Until now, I had the data frame loaded in the workspace, let's call it "mydata".
So in my UI area I had things like:
selectInput('varX3', "Variable 3", choices = names(mydata))
and worked perfectly.
But now I have decided to implement another module in the app where I can import data from a CSV, so I import the data, I check if the data is correct and then click a button called "confirm" that creates a reactive object, mydata().
What's the problem now? Well, there are two main problems:
mydata doesn't exist anymore, so when compiling it fail.
if I change mydata for mydata() in the UI, it will make an error too since mydata() doesn't exist until I import the data and confirm the data imported is OK and also there's no supposed to be reactive objects in the UI (as far as I know).
I have come up with the solution of using renderUI and uiOutput, but I found tedious to change everything.
Is there another way of solving the problem?
To explain me better:
first: I import data from a CSV and check if the data is OK, click a button creating a reactive object, a dataframe with the data: mydata()
second: I make plots of the variables of this data frame, so the data frame appears in the UI necessarily.

Manipulating a user-uploaded file/data in R shiny

I've been working on an R shiny app that is supposed to take a user-uploaded .csv file, do a bunch of manipulations/calculations to that data, and then spit out some graphs. I am completely new to shiny, however, and am very lost. I've tried to look this up, but most results I found take the data and directly show it in a graph. So far I've tried this (code is taken from here):
UI:
ui <- fluidPage(
fileInput("userfile", "Choose CSV File", multiple = TRUE,
accept=c("text/csv","text/comma-separated-values,text/plain",".csv")),
# etc.
Server:
server <- function(input,output){
df <- read.csv(input$userfile$datapath)
# some manipulation, such as adding a new column, for example:
df$timestwo <- 2 * df$column1
}
Is df in the Server code supposed to be the dataframe that was read in from the user-uploaded file? If not, how can I create a dataframe that is able to go through several changes, before making a graph? When I try to run my code I get "Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer." Thanks!
Edit to add: all the data manipulation I wanted to do worked with my sample dataset, but not the user-input one I tried out (which was the exact same data).

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.

How to convert a Shiny app consisting of multiple files into an easily shareable and reproducible Shiny example?

There are resources on how to create a Minimal, Complete, and Verifiable example in general on Stack Overflow, and on how to make a great R reproducible example. However, there are no similar guidelines for shiny questions, while adhering to certain standards makes it much more likely that quality answers will be given, and thus that your question will be resolved.
However, asking a good Shiny question can be difficult. shiny apps are often large and complex, use multiple data sources, and the code is often split over multiple files, making it difficult to share easily reproducible code with others. Even though a problem may be caused in server.R, the example is not reproducible without the contents of ui.R (and possibly other files like stylesheets or global.R). Copy-pasting the contents of all these files individually is cumbersome, and requires other users to recreate the same file structure to be able to reproduce the problem.
So; how to convert your shiny app into a good reproducible example?
Example data
Of course, all guidelines regarding sample data mentioned in the answer on the question “how to make a great R reproducible example” also hold when creating questions related to Shiny. To summarize: Make sure no additional files are needed to run your code. Use sample datasets like mtcars, or create some sample data with data.frame(). If your data is very complex and that complexity is really required to illustrate the issue, you could also use dput(). Avoid using functions like read.csv(), unless of course you have questions related to functions like fileInput.
Example code
Always reduce your code to the bare minimum to reproduce your error or unexpected behavior. This includes removing calls to additional .CSS files and .js files and removing unnecessary functions in the ui and the server.
Shiny apps often consist of two or three files (ui.R, server.R and possibly global.R), for example this demo application. However, it is preferable to post your code as a single script, so it can easily be run by others without having to manually create those files. This can easily be done by:
wrapping your ui with ui <- fluidPage(…),
the server with server <- function(input,output, session) {…},
and subsequently calling shinyApp(ui, server).
So a simple skeleton to start with could look as follows:
library(shiny)
ui <- fluidPage(
)
server <- function(input,output,session) {
}
shinyApp(ui, server)
Working Example
So, taking all the above into account, a good Minimal, Complete, and Verifiable example for a Shiny application could look as follows:
library(shiny)
df <- data.frame(id = letters[1:10], value = seq(1,10))
ui <- fluidPage(
sliderInput('nrow', 'Number of rows', min = 1, max = 10, value = 5),
dataTableOutput('my_table')
)
server <- function(input, output, session) {
output$my_table <- renderDataTable({
df[1:input$nrow,]
})
}
shinyApp(ui, server)
Adding CSS
There are multiple ways to add custom CSS to a Shiny application, as explained here. The preferred way to add CSS to a Shiny application in a reproducible example is to add the CSS in the code, rather than in a separate file. This can be done by adding a line in the ui of an application, for example as follows:
tags$head(tags$style(HTML('body {background-color: lightblue;}'))),

Resources