Home > Net >  Why is parse(text=) throwing an error when there is a comma in the text?
Why is parse(text=) throwing an error when there is a comma in the text?

Time:09-21

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)
  • Related