Currently I have a function [degtest] which is created in the shiny server, that returns a list,
return(list(datatable=datatable, predicttable=predicttable, esttable=esttable)
I want this list to be accessible after the function has run so that I can use different parts of the list to be rendered separately.
outlist <- reactive({
if(is.null(input$file2)){return(NULL)}
if(input$d2 == 0){return(NULL)}
with(data = reactdata$degdata, degtest(reactdata$degdata[,input$selectTemp], reactdata$degdata[,input$selectPot],reactdata$degdata[,input$selectWeight], reactdata$degdata[,input$selectTime], input$Temp0))
})
input$file2 is my reactdata (reactdata$degdata and input$d2 is an action button.
I thought i'd be able to reference outlist$datatable but R says ' object of type 'closure' is not subsettable'
When you are making an object reactive, you are actually making it into a sort of function (closure), so you have to use it as outlist() rather than outlist. See this similar question. It's hard to answer your question considering you did not provide a reproducible example, but I think your solution will be something like outlist()$ObjectYouAreTryingToAccess.
Related
I was trying to code a shiny application that loads a Rdata based on the input of the users, filters it, and graphs the result. All Rdata files are located in a folder and follow the same name format. Here is the example of my code for the server.
server <- function(input, output) {
data <- reactive({load(paste0("themewise_final_datasets/final_", input$Theme, "_theme.RData"))})
data_filtered <- reactive({data() %>%
filter(str_detect(locations, input$location))})
output$average_tone_graph <- renderPlot({
data_filtered() %>%
# below there were irrelevant code graphs.
The problem with this code is that even though the server loads the rdata, it doesn't filter it. I get the error UseMethod: no applicable method for 'filter' applied to an object of class "character". I couldn't fix it. I thought it might be because the columns are factors and tried to fix that, but that is not the problem.
This error happens when you try to apply a data type to a generic method like filter for which your system does not have a specific implementation. You can check what data types your environment supports (given the loaded packages) with ...
methods(filter)
At my system I get the result
#' [1] filter.data.frame* filter.ts*
which means, that I can apply the filter method on base R data frames and time series objects. Something similar seems to be the case on your system. From the error message you can learn that the input you provide for filter is of class character. If methods(filter) does not return a method for those, you have two options: find an implementation for filter that can handle character vectors; change the type of data(); or use a different way to filter the vector like this:
data()[str_detect(locations, input$location)]
I am working with shiny on Mac. I try to make elements in df$Trail_id clickable. I see a similar one,Convert a column of text URLs into active hyperlinks in Shiny, I try the similar code as,enter image description here
But here is the return error message, Error: 'data' must be 2-dimensional(eg.data frame or matrix).
But TI_result_score is a table which I use read.table to input it before DT::renderDataTable.
No idea what is the problem.
Best
Max
The "escape" argument should be inside a datatable function, not renderDataTable. Moreover, renderDataTable is a function with arguments. So I think that the vector modified by your paste0 is what is taken for the "table" argument by the function, and not the data.frame itself. That would explain the dimension exception thrown.
This should work :
output$TI_scores <- DT::renderDataTable({
TI_result_scores$Trail_id <- paste0(...) #your code here
datatable(TI_result_scores,escape=FALSE)
})
Tell us if there is still a problem.
Regards
In the RShiny package (for web applications) you have reactive variables (update automatically when something in the UI changes). When you use these variables you need to use this syntax: variable() with brackets at the end of the variable name.
I need this reactive variable as input for one of my functions. I call this function in the server.R part. There I use function(infile = fa_archive(), ...) but R thinks that fa_archive() is a function instead of a variable. Probably because of the parentheses, but it isn't. I am 100% sure the variable fa_archive is defined. Beforehand I only needed fa_archive[[1]]() as input and then my function worked fine. But now I needed to "upgrade" my function as to include more files at once and when I use fa_archive() as input variable in the function it recognizes it as a function and returns
Error: Could not find function "fa_archive()"
I have not really tried solving this, because it just seems so weird that using the full variable instead of a part of it ([[1]]) should change this so drastically. Here is the relevant piece of my code
fa_archive <- list(
reactive({ fa_archive_function(input$model1, as.integer(input$lag1)) }),
reactive({ fa_archive_function(input$model2, as.integer(input$lag2)) }),
reactive({ fa_archive_function(input$model3, as.integer(input$lag3)) }),
reactive({ fa_archive_function(input$model4, as.integer(input$lag4)) }))
output$plotSounding1Da <- renderPlot({ plot_profile(infile= fa_archive() , fcdate=fcdate(), ldt=ldt(), prm=input$prmSounding, location=input$location, recent=recent(), add=FALSE)}, width=400, height=500)
When you use [reactive] variables you need to use this syntax: variable() with brackets at the end of the variable name.
Correct. But this only works on a reactive variable. And your fa_archive() isn’t a reactive variable, it’s a normal R lits. That’s why R complains.
Just surrounding the list call with reactive(…) probably won’t work though, because your code has other issues that need fixing. Without knowing what exactly plot_profile does, it’s unlikely that it expects a list of reactive components as an argument.
I am new to R Shiny and I am trying to create an app which I need it to be as interactive as possible. One problem that I am dealing with is this. In the ui.R I have the following:
helpText("Select a feature"),
uiOutput("sliders")
And in the server.R:
output$sliders <- renderUI({
selectInput('feature_name',
'Feature name', #Description
choice = c("F1"='1', "F2"='2'))
})
My question is that is it possible to change something in renderUI so that instead of setting c("F1"='1', "F2"='2')) statically I can pass the results of a function to it so it can be more dynamic (a function which generates a feature list based on something that user does and passes the list to renderUI to create the selectInput). Something like following:
output$sliders <- renderUI({
selectInput('feature_name',
'Feature name', #Description
choice = c(feature_creator(method)))
})
Where "feature_creator" is a function and it returns: "F1"='1', "F2"='2' based on the method selected by user (variable "method" is defined and I have the value). My question to be more specific is what should "feature_creator" return as output?
Hope my question is clear enough. Let me know if I should add anything to the problem description.
Any help will be much appreciated. Thanks
Assuming that all you really need is the method argument, this is not hard.
1) Make a radioButtons() input in your ui that will let the user select a method, lets give it inputId="MethodChoice".
2) In your choice argument in the selectInput you should use choice=c(feature_creator(input$MethodChoice))
Then feature_creator will get a text value based on the method the user chooses.
In order to work in choice, feature_creator should return a named list, similar in format to what you hard-coded.
I'm drafting a simple Shiny App that provides access to a dynamic chart and a corresponding table. The relevant part of the server.R code looks like that:
output$some_plot<- renderPlot({
# Subset data on change in the indicator selection
chrt_demo_dta <- subset(x = dta_la_demo,
subset = <<my-conditions>>>)
# Define the demography chart
ggplot(data = chrt_demo_dta, aes(x = variable_a, y = variable_b)) +
geom_line(aes(colour = GEOGRAPHY_NAME), size = 2) +
theme_bw()}, height = 650, width = 800)
# Section generating table
output$chrt_demo_dta_tbl <- renderTable({chrt_demo_dta})
The problem occurs when I try to access the table I get the following error message:
Error in func() : object 'chrt_demo_dta' not found
It appears that the object chrt_demo_dta is created outside the scoping rules of the renderTable. My question is how can I achieve the following:
I want for the chart and the corresponding table to update dynamically upon the selection, hence my idea to embed the subset command in the renderPlot which works
I want to make use of the same subset in a corresponding table. Ideally, I would like to avoid repeating the subset command. As I have the required data frame ready it appears that it is only a matter of accessing it via the renderTable
I'm aware the the code is not fully reproducible but at this stage I'm not necessarily looking for a particular solution but a more generic guidance whether it would be possible to access an object created within one server element from other server element. If the push comes to shove, I could encapsule the subsetting mechanism in a function and call it twice but it seems to be rather messy solution.
In the server function of server.R:
# Create reactive object w/in server func
chrt_demo_dta <- reactiveVal()
output$some_plot<- renderPlot({
chrt_demo_dta.temp <- subset(
x = dta_la_demo,
subset = <<my-conditions>>>)
# Update the obj within scope of nested function
chrt_demo_dta(chrt_demo_dta.temp)
})
# Access of the updated obj is now possible in original scope
output$chrt_demo_dta_tbl <- renderTable({chrt_demo_dta()})
See related: Shiny : How to modify reactive object
The <<- operator may have unwanted consequences. It sends results to the shared environment, where it is visible to all users of the session. Not only will this create a race-condition where they try to over-write each other, it may expose confidential work to others. You have two solutions: 1) repeat the steps in each local environment, 2) write the result to disk with a unique name (e.g. Sys.time() + data hash). Then you can retrieve it when needed elsewhere. Don't forget to delete the saved file though, or your storage will be consumed.