1

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.

  • 1
    From `?deparse`: the default for the backtick option is not to quote single symbols but only composite expressions. This is a compromise to avoid breaking existing code. Have a look at `substitute(\`bad_name\`)` vs `deparse(subsitutte(\`bad_name\`))` vs `deparse(substitute(\`bad_name\`), backtick = T)`. However, when I run `my_fun(df, \`bad name\`)` the result is fine. – Donald Seinen Dec 07 '21 at 13:37
  • @DonaldSeinen Running my_fun(df, \`bad name\`) for the long version `my_fun` results in this error for me: Error in parse(text = transform_i) : :1:5: unexpected symbol 1: bad name ^ –  Dec 07 '21 at 13:44

1 Answers1

1

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.

Donald Seinen
  • 4,179
  • 5
  • 15
  • 40