Home > Enterprise >  How to prevent `...` to disappear inside of deparse(substitute(x))
How to prevent `...` to disappear inside of deparse(substitute(x))

Time:12-07

Short version

Consider this function:

my_fun <- function(x){
  deparse(substitute(x))
}

Why does the function remove the ` if nothing else than one variable name is added? See here:

my_fun(`bad name`)
"bad name"
my_fun(`bad name` - 1)
"`bad name` - 1"

Long version

I wrote a simple function that takes a dataframe and does some transformation with choosen columns. This is the function:

my_fun <- function(data, transform){
  transform <- deparse(substitute(transform))
  transform <- unlist(strsplit(transform, "\\ "))
  out <- do.call("cbind.data.frame", lapply(transform, function(transform_i){
    eval(parse(text= transform_i), data)
  }))
  names(out) <- transform
  return(out)
}

With this function we can do stuff like this:

# Create data.
df <- data.frame(matrix(rep(1:4, 2), ncol= 2))
names(df) <- c("good_name", "bad name")

# Transform data with function.
my_fun(df, sqrt(good_name)   sqrt(`bad name`) - 1)
  sqrt(good_name)   sqrt(`bad name`) - 1
1         1.000000             0.0000000
2         1.414214             0.4142136
3         1.732051             0.7320508
4         2.000000             1.0000000

But the function fails if we enter a name containig a white space like here: my_fun(df, `bad name`). I noticed that deparse(substitute(transform)) removes the ` if I make no transformation. See here:

my_fun <- function(data, transform){
  deparse(substitute(transform))
}
my_fun(df, `bad name`)
"bad name"
my_fun(df, `bad name` -1)
"`bad name` - 1"

How can I prevent deparse(substitute(transform)) removing the `?

I know that there are many ways out there to transform dataframe like my function does. For example, we could use with(df, `bad name` -1) and with(df, `bad name`) here. But that is not the question.

CodePudding user response:

From the help file ?default: The default for the backtick option is not to quote single symbols but only composite expressions. This SO post hints at looking at the ?Quotes help file - we can escape backticks using a backslash if needed.

In this example, one may try setting the backtick argument of the deparse function to TRUE. To compare different approaches, and how combinations are deparsed, consider the following situations:

substitute(`bad name`)
#> `bad name`

deparse(substitute(`bad name`))
#> [1] "bad name"

deparse(substitute(`bad name`), backtick = T)
#> [1] "`bad name`"

# and see this fail:
substitute(`bad name)

# and this return
deparse(
  deparse(substitute(`bad name`))
)
#> "\"bad name\""

deparse(substitute(
  `deparse(substitute(bad name))`
))
#> [1] "deparse(substitute(bad name))"

deparse(substitute(
  `deparse(substitute(`bad name`))`
))
#> Error: unexpected symbol in:
#> "deparse(substitute(
#>  `deparse(substitute(`bad"
#> > ))
#> Error: unexpected ')' in ")"

# but
deparse(substitute(
  `deparse(substitute(\`bad name\`))`
))
#> [1] "deparse(substitute(`bad name`))"

If the intent is to enforce character names, have a look at deparse1 for R4.0.0 (April 2020) and later.

  • Related