Inside of a Shiny app I am combining levels to make a ID that will be used for ggplot faceting.
Here is an example of what works when doing it by hand:
paste0(data[[1]],', ',data[[2]])
However, the user can select whatever and how ever many identifying columns they want, so I am automating it like this:
First I build combo_ID_build from whatever columns they have selected in UI1 (which is numeric with column numbers for whatever the user selected).
for (i in UI1){
combo_ID_build<-paste0(combo_ID_build,"data[[",i,"]]")
if(i != tail(UI1,1)){
combo_ID_build<-paste0(combo_ID_build,",', ',")
}
}
Then I use eval(parse())
ID <- paste0(eval(parse(text = combo_ID_build)))
So for this example, the user selects columns 1 and 2, so combo_ID_build would be "data[[1]],', ',data[[2]]"
where str(combo_ID_build) is chr.
However, when parsed this throws an error, "Error in parse(text = combo_ID_build) : :1:10: unexpected ',' 1: data[[1]],"
I tried escaping the comma with \ and \\ but it only throws an error about the backslashes being unrecognized escape strings.
What am I doing wrong here?
CodePudding user response:
You eval(parse())
tries to parse and evaluate an expression. You run
eval(parse(text = "data[[1]],', ',data[[2]]"))
That's equivalent to running the command
data[[1]], ', ', data[[2]]
which indeed is a syntax error. It doesn't matter that you wrapped it in paste0
, when you have foo(bar())
foo()
will run on the output of bar()
. If bar()
can't run on its own, there will be an error. You have paste0(eval(parse())
, paste0()
will run on the output of eval()
. So what you eval()
needs to run on its own before paste0()
is called.
eval(parse())
should usually be avoided. In this case, I think you're looking for do.call
, which lets you call a function on a set of arguments in a list
. Let's also use paste
with sep = ", "
to simplify things:
# no loop or eval/parse needed
combo_ID_build = do.call(what = \(x) paste(x, sep = ", "), args = data[UI1])
In this particular case, we can simplify even more by using the utility function interaction()
which is made for this use case:
combo_ID_build = interaction(data[UI1], sep = ", ")
I'll leave you with this:
fortunes::fortune(106)
# If the answer is parse() you should usually rethink the question.
# -- Thomas Lumley
# R-help (February 2005)