Upload a .xlsx file to Shiny and load in all the tabs as a list [duplicate] - r

I have a shiny app and when I run it I get an error saying that an object of type ‘closure’ is not subsettable. What is that and how can I fix it?
Note: I wrote this question as this comes up a lot, and the possible dupes are either not shiny related or so specific that it is not obvious that the answers are broadly applicable.

See also this question which covers this error in a non-Shiny context.
How to fix this:
This is a very common error in shiny apps. This most typically appears when you create an object such as a list, data.frame or vector using the reactive() function – that is, your object reacts to some kind of input. If you do this, when you refer to your object afterwards, you must include parentheses.
For example, let’s say you make a reactive data.frame like so:
MyDF<-reactive({ code that makes a data.frame with a column called “X” })
If you then wish to refer to the data.frame and you call it MyDF or MyDF$X you will get the error. Instead it should be MyDF() or MyDF()$X You need to use this naming convention with any object you create using reactive().
Why this happens:
When you make a reactive object, such as a data.frame, using reactive() it is tempting to think of it as just like any other non-reactive data.frame and write your code accordingly. However, what you have created is not really a data.frame. Rather, what you have made is instructions, in the form of a function, which tell shiny how to make the data.frame when it is needed. When you wish to actually use this function to get the data.frame you have to use the parenthesis, just like you would any other function in R. If you forget to use the parenthesis, R thinks you are trying to use part of a function and gives you the error. Try typing:
plot$x
at the command line and you will get the same error.
You may not see this error right when your app starts. Reactive objects have what is called “lazy” evaluation. They are not evaluated until they are needed for some output. So if your data.frame is only used to make a plot, the data.frame will not exist until the user sees the plot for the first time. If when the app starts up the user is required to click a button or change tabs to see the plot, the code for the data.frame will not be evaluated until that happens. Once that happens, then and only then will shiny use the current values of the inputs to run the function that constructs the data.frame needed to make the plot. If you have forgotten to use the parentheses, this is when shiny will give you the error. Note that if the inputs change, but the user is not looking at the plot, the function that makes the data.frame will not be re-run until the user looks at the plot again.

Related

Is attributes() a function in R?

Help files call attributes() a function. Its syntax looks like a function call. Even class(attributes) calls it a function.
But I see I can assign something to attributes(myobject), which seems unusual. For example, I cannot assign anything to log(myobject).
So what is the proper name for "functions" like attributes()? Are there any other examples of it? How do you tell them apart from regular functions? (Other than trying supposedfunction(x)<-0, that is.)
Finally, I guess attributes() implementation overrides the assignment operator, in order to become a destination for assignments. Am I right? Is there any usable guide on how to do it?
Very good observation Indeed. It's an example of replacement function, if you see closely and type apropos('attributes') in your R console, It will return
"attributes"
"attributes<-"
along with other outputs.
So, basically the place where you are able to assign on the left sign of assignment operator, you are not calling attributes, you are actually calling attributes<- , There are many functions in R like that for example: names(), colnames(), length() etc. In your example log doesn't have any replacement counterpart hence it doesn't work the way you anticipated.
Definiton(from advanced R book link given below):
Replacement functions act like they modify their arguments in place,
and have the special name xxx<-. They typically have two arguments (x
and value), although they can have more, and they must return the
modified object
If you want to see the list of these functions you can do :
apropos('<-$') and you can check out similar functions, which has similar kind of properties.
You can read about it here and here
I am hopeful that this solves your problem.

R: Getting more informative error messages in R

I am still not very good at using R’s standard debugging tools, and I often find that neither the error nor the traceback tell me enough to figure out what is going on. I would like to change R’s default behavior on error to provide more information.
Specifically, I would always like the call, including the formals, the expression assigned to each formal (the default expression if the default is the expression assigned), and the value of each of the argument expressions as evaluated in place, all returned in a format that makes it unambiguous which expression has been matched to which formal and which values go with which expression. Since the values might be large or of unexpected or evanescent type, I’d like them to be returned in a format, such as a str(), that makes intelligent choices about truncation and correctly identifies promises and other object types that tend to evaluate themselves into something else before you see them.
And finally, I’d like all these things, together with the return value of each call, for every function on the call stack from the error back to (and including) some piece of code that I wrote. It seems to me that the natural structure would be a single R object, a list of lists, one list per call (perhaps tidied, broom-like, into a tibble with some list columns) that I could single-step through in the obvious way.
I apologize if I have described some standard R debugging tool that I just haven't learned how to use properly yet. Is this even possible? If it is, could it be implemented via R's available error handlers, or would it need some package-scale coding project?
I would most prefer a solution that changes the default error response to this, but if that is impracticable, I'd accept a solution that requires that I rerun a code chunk with a wrapper or something similar.

Create an arbitrary number of plots with inputs in shiny using modules

Thank you very much for your time and help!
My goal: create an arbitrary number of plots (ggplot2) in shiny where each comes with a number of controls (y axis min/max, plot download button, plot, hover info for the plot). Important: implement it using shiny modules, where a module is created to build a single ui element and another module calls the single element module and loops to create an arbitrary number of ui elements (I can get it to work without using modules).
It works for me if the data for the plots (and the vector which is used to loop over to create each plot) are loaded globally in the app. This global data gist demonstrates my use case using iris dataset loaded globally. Here how it looks like when it works: snapshot of the app
However, my problem is that I can't figure out how to write a shiny module when the data are not loaded globally. Real life example: I pull the data from a database, do some processing on the server side and then I want to generate the plots. Reproducible example using the iris dataset loaded on the server side: server data gist
The error I get when the data are loaded on the server side (when running server data gist):
Error in as.vector: cannot coerce type 'environment' to vector of type 'character'
I believe this is something to do with how I write the module for the multiple ui elements (I suspect multiplePlotsUI).
My question: What will be the correct way to write the module that calls another module and loops over a vector to generate an arbitrary number of ui elements (y axis controls, plot download button, plot with hover info) when the data are not loaded globally?
I don't know if it'll help, but as far as I can see, your input.data() function is not defined in you multiplePlots call (local.data <- input.data())
You're also calling
dm <- dat()
twice, but this dat() function doesn't seem to be defined

R shiny ERROR: object of type 'closure' is not subsettable [duplicate2] [duplicate]

I have a shiny app and when I run it I get an error saying that an object of type ‘closure’ is not subsettable. What is that and how can I fix it?
Note: I wrote this question as this comes up a lot, and the possible dupes are either not shiny related or so specific that it is not obvious that the answers are broadly applicable.
See also this question which covers this error in a non-Shiny context.
How to fix this:
This is a very common error in shiny apps. This most typically appears when you create an object such as a list, data.frame or vector using the reactive() function – that is, your object reacts to some kind of input. If you do this, when you refer to your object afterwards, you must include parentheses.
For example, let’s say you make a reactive data.frame like so:
MyDF<-reactive({ code that makes a data.frame with a column called “X” })
If you then wish to refer to the data.frame and you call it MyDF or MyDF$X you will get the error. Instead it should be MyDF() or MyDF()$X You need to use this naming convention with any object you create using reactive().
Why this happens:
When you make a reactive object, such as a data.frame, using reactive() it is tempting to think of it as just like any other non-reactive data.frame and write your code accordingly. However, what you have created is not really a data.frame. Rather, what you have made is instructions, in the form of a function, which tell shiny how to make the data.frame when it is needed. When you wish to actually use this function to get the data.frame you have to use the parenthesis, just like you would any other function in R. If you forget to use the parenthesis, R thinks you are trying to use part of a function and gives you the error. Try typing:
plot$x
at the command line and you will get the same error.
You may not see this error right when your app starts. Reactive objects have what is called “lazy” evaluation. They are not evaluated until they are needed for some output. So if your data.frame is only used to make a plot, the data.frame will not exist until the user sees the plot for the first time. If when the app starts up the user is required to click a button or change tabs to see the plot, the code for the data.frame will not be evaluated until that happens. Once that happens, then and only then will shiny use the current values of the inputs to run the function that constructs the data.frame needed to make the plot. If you have forgotten to use the parentheses, this is when shiny will give you the error. Note that if the inputs change, but the user is not looking at the plot, the function that makes the data.frame will not be re-run until the user looks at the plot again.

Working with "..." input in R function

I am putting together an R function that takes some undefined input through the ... argument described in the docs as:
"..." the special variable length argument ***
The idea is that the user will enter a number of column names here, each belonging to a dataset also specified by the user. These columns will then be cross-tabulated in comparison to the dependent variable by tapply. The function is to return a table (independent variable x indedependent variable).
Thus, I tried:
plotter=function(dataset, dependent_variable, ...)
{
indi_variables=list(...); # making a list of the ... input as described in the docs
result=with (dataset, tapply(dependent_variable, indi_variables, mean); # this fails
}
I figured this should work as tapply can take a list as input.
But it does not in this case ('Error in tapply...arguments must have same length') and I think it is because indi_variables is a list of strings.
If I input the contents of the list by hand and leave out the quotation marks, everything works just fine.
However, if the user feeds the function the column names as non-strings, R will interpret them as variable names; and I cannot figure out how to transform the list indi_variables in the right way, unsuccessfully trying things like this:
indi_variables=lapply(indi_variables, as.factor)
So I am wondering
What causes the error described above? Is my interpretation correct?
How would one go about transforming the list created through ... in the right way?
Is there an overall better way of doing this, in the input or the implementation of tapply?
Any help is much appreciated!
Thanks to Joran's helpful reading, I have come up with these improvements than make things work out...
indi_variables=substitute(list(...));
result=with (dataset, tapply(dependent_variable, eval(indi_variables, dataset), FUN=mean));

Resources