I stored several tables in .rds files which I would like to import using readRDS in a Shiny session. Therefore I defined the following global function:
get.station <- function(sname){
file.name <- paste(sname".rds", sep="")
return(readRDS(file.name))
}
within the server function I define the reactive value:
st.reactive <- reactiveValues(get.station(input$station.sel))
where input$station.sel comes from the ui using selectInput(...). This results in the following error message:
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.)
This error message even does not disappear if I define this function using reactive():
get.station <- reactive({
file.name <- paste(input$station.sel".rds", sep="")
return(readRDS(file.name))
})
and within the server:
st.reactive <- reactiveValues(data=get.station())
Do you have any help?
You've got the right idea, just put the function inside a reactive or observe_ function. While you can define reactiveValues in the initial call, its best, in my opinion, to create the reactive values object empty and then do all your assignments with the <- notation.
The confusion comes from the fact that, despite it's name, reactiveValues is not a reactive expression. It generates a reactiveValues object that reactive values can be stored in, but it only runs once and does not check whether its values are invalidated.
In your case, I'd do the following:
rv <- reactiveValues()
rv$st.reactive <- observe({get.station(input$station.sel)})
Related
I am very new to Shiny and R in general and I am building an app that allows users to import data, select their variables, number of trees.. ect and then run that through a random forest script and have it display the outputs. Right now I am just working on the inputs, however, I am running into a problem. The user can import a CSV but then they cannot select their variables (headers from csv). I am trying to make it reactive so the user first must import their csv before the option of selecting their variables pops up (seems simple).
Here is my code right now:
ui.R
server.R
Error in Console
I am probably just making a silly mistake because I am unfamiliar with Shiny but your help would be much appreciated.
A little background info
First off, I recommend you read this through to get a good understanding of reactivity in Shiny: Shiny Reactivity Overview. This helps a lot with variable scoping in a Shiny context too: Scoping Rules in Shiny Apps.
The issue
I believe this issue is due to you defining the variable file_to_read within the scope of shiny output: output$input_file in your server.R file. When the function read.table() looks for the variable file_to_read, it doesn't exist since it is only defined within the scope of the shiny output.
Try making a reactive value and then assigning the input$file value to it once it is uploaded by the user. You'll also have to convert your dat1 variable to a shiny reactive since you can only read reactive values in the context of other reactive sources (e.g. observe(), reactive(), observeEvent(), etc.)
file_to_read <- reactiveVal(NULL) # Set the value to NULL to initialize
output$input_file <- renderTable({
if (is.null(input$file)) return () # Check there is an input file
file_to_read(input$file) # Set the reactiveVal to the input file
})
# Make dat1 a reactive so it can be read within a shiny reactive
dat1 <- reactive({
if(is.null(file_to_read()) return (NULL) # Check for input file in reactiveVal
read.table(file_to_read()$datapath, sep = input$sep, header = input$header)
})
# Make an eventReactive to capture when there is read.table() data from dat1
reactive1 <- eventReactive(dat1, {
if (is.null(dat1)) return ()
D <- colnames(dat1)
return (list(D, D[1]))
})
I didn't test this code since you posted your data in image format and I don't have an input file, but hope this helps your error.
I am trying to pass a simple integer to a Shiny Flexdashboard. But I can for some reason only to it staticly, but I'd rather have it reactivly;
aggregated_static <- readRDS( "../rdsdata/aggregated_static.rds")
k <- nrow(aggregated_static)
That piece of code passes the number of rows to my Shiny dash, where it can be accessed with;
item_lines = k
But, if I do it this way, it won't work, telling me I can't access reactive content from that spot;
set_aggregated <- reactiveFileReader(1000, session, "./rdsdata/set_aggregated.rds", readRDS)
k <- nrow(aggregated_static())
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.)
Now I've tried using Isolate, creating a function enclosing that with reactive({}), but I am simply nog getting that value passed. Is there a way to do this?
If you want the value of k to be reactive, you should wrap it in reactive(), i.e.:
k <- reactive(nrow(aggregated_static()))
and then call its value as k()
The following function fails:
get_num <- function(input$num){ans <-input$num
return(ans)}
since R is confused by the $ symbol.
Although this is a toy example, I would like to write a function that directly takes reactive input values (in this case, a number) and does something meaningful with them, without having to preempt the situation with
num <- input$num
get_num <- function(num){ans <-num
return(ans)}
Is this even possible?
There are three points here:
when you are dealing with reactive values, you use reactive() instead of function() in your script.
Here is example:
num_square = reactive({input$num^2})
observe(print(num_square()))
The first line defines a new reactive values base on input$num and second lines print it as soon as it changes. Note that reactive values are same as function, and you should call them with () in front of them.
when you want to save a value to outside environment (other that internal use of function or reactive) you should use <<- instead of = or <- notation.
Here is an example:
reactive1 <- reactive({num_square <<- input$num^2
print(num_square) })
The above line changes the value of num_square as soon as you run reactive1() some place in your code. note that without running reactive1() the value of num_square wont change. This is the BIG DIFFERENCE between reactive() (lazy evaluation) and observe() (eager evaluation).
observe() is another method to use reactive values in a function. It seems to me that you are looking for this one.
Here is an example. The value of get_num will change as soon as you change input$num in your program.
observe({get_num <<- input$num
print(get_tmp)})
Note that above script should be in middle of shinyServer(function(input, output) { ... }).
Difference between reactive() and observe(): [refer to: http://shiny.rstudio.com/reference/shiny/latest/observe.html ]
An observer is like a reactive expression in that it can read reactive
values and call reactive expressions, and will automatically
re-execute when those dependencies change. But unlike reactive
expressions, it doesn't yield a result and can't be used as an input
to other reactive expressions. Thus, observers are only useful for
their side effects (for example, performing I/O).
Another contrast between reactive expressions and observers is their
execution strategy. Reactive expressions use lazy evaluation; that is,
when their dependencies change, they don't re-execute right away but
rather wait until they are called by someone else. Indeed, if they are
not called then they will never re-execute. In contrast, observers use
eager evaluation; as soon as their dependencies change, they schedule
themselves to re-execute.
Try:
get_num <- function(ans = input$num) {
out <- seq(ans:ans*2)
return(out)
}
get_num()
or:
get_num <- function(ans) {
out <- seq(ans:ans*2)
return(out)
}
get_num(input$num)
I think a more natural way to do this in shiny is to use reactive like so:
get_num<-reactive({ ans<-input$num)}
Obviously you could do more, like:
get_num<-reactive({ans<-input$num*20
ans<-ans/pi
})
or whatever. Then refer to your value as get_num() as it is now a function.
I need to use:
session$clientData$url_search
which is a reactive expression but I don't want to use it in a reactive wrapper, i.e.
sessionData <- reactive({
sessionData <- session$clientData$url_search
})
is there a way to now use this session data in a non reactive way? i.e.
url <- paste("http://example.web.ninja/,sessionData,sep="")
URLdata <- fromJSON(file=url,method='C')
without having to use:
URLdata <- reactive({
url <- paste("http://example.web.ninja/,sessionData(),sep="")
URLdata <- fromJSON(file=url,method='C')
})
Thanks
In this case the error:
Error in URLdata$Name : object of type closure is not subsettable
indicates that the object needs to be referenced as
URLdata()$Name
This results in a call to the reactive function. Calling a reactive variable within a reactive environment endows that reactive environment with a dependency on that reactive variable. Quickly things can cascade so there is a handy function isolate which allows one to call a reactive variable in a reactive environment and not bestow that dependency. In your case accessing the required object using
isolate(URLdata()$Name)
may be what you want.
Any ideas on how to update a data frame that shiny is using without stopping and restarting the application?
I tried putting a load(file = "my_data_frame.RData", envir = .GlobalEnv) inside a reactive function but so far no luck. The data frame isn't updated until after the app is stopped.
If you just update regular variables (in the global environment, or otherwise) Shiny doesn't know to react to them. You need to use a reactiveValues object to store your variables instead. You create one using reactiveValues() and it works much like an environment or list--you can store objects by name in it. You can use either $foo or [['foo']] syntax for accessing values.
Once a reactive function reads a value from a reactiveValues object, if that value is overwritten by a different value in the future then the reactive function will know it needs to re-execute.
Here's an example (made more complicated by the fact that you are using load instead of something that returns a single value, like read.table):
values <- reactiveValues()
updateData <- function() {
vars <- load(file = "my_data_frame.RData", envir = .GlobalEnv)
for (var in vars)
values[[var]] <- get(var, .GlobalEnv)
}
updateData() # also call updateData() whenever you want to reload the data
output$foo <- reactivePlot(function() {
# Assuming the .RData file contains a variable named mydata
plot(values$mydata)
}
We should have better documentation on this stuff pretty soon. Thanks for bearing with us in the meantime.