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.