using substitute to get argument name with
The canonical idiom here is deparse(substitute(foo))
, but the ...
needs slightly different processing. Here is a modification that does what you want:
foo <- function(a, ...) {
arg <- deparse(substitute(a))
dots <- substitute(list(...))[-1]
c(arg, sapply(dots, deparse))
}
x <- 1
y <- 2
z <- 3
> foo(x,y,z)
[1] "x" "y" "z"
base R substitute names of the arguments to function call
Assuming that the question is how to produce a call
object whose function is the first argument of params
, whose single argument name is the value of the second component of params
and whose argument value is the third component of params
then c2
is that call object. We verify that the cakl object produced is identical to the rlang call object shown in the question.
c2 <- as.call(setNames(params, c("", "", params2$my_name))[-2])
# verify that c2 equals the output of the rlang example in question
c1 <- with(expr = rlang::call2(my_fun, !!my_name := my_value), data = params)
identical(c1, c2)
## [1] TRUE
This generalizes so that if the call has more arguments so that params has length n+2 and the second component of params
is a vector of names whose length is n then it still works.
If you have control over the input I think it would make more sense to define the input list as having one component for the function name and one component for each argument with the names of the components being the argument names (as opposed to a separate argument to hold the names). In that case we could simply write the following. Actually what the above does is to transform params into that form and then use as.call so we might as well provide that form from the start if possible.
as.call(params2) # params2[[1]] is func name, params2[-1] is named args
Note
To execute the call just use:
eval(c2)
or we could use do.call
:
do.call(as.character(params[[1]]), setNames(tail(params, -2), params[[2]]))
Use substitute() to replace a label/argument name
x
is bound to a name. We can see that with
as.list(substitute(list(x = y)))
# [[1]]
# list
#
# $x
# y
So it's not terribly easy to change the name within the substitute
call. But you can do
e <- substitute(list(x = y), list(y = "bar"))
names(e)[2] <- "foo"
eval(e)
# $foo
# [1] "bar"
or with just substitute
you can change the expression to use setNames
e <- substitute(setNames(list(y), x), list(x = "foo", y = "bar"))
eval(e)
# $foo
# [1] "bar"
But you can also use call
, which is easier
cl <- call("list", foo = "bar")
eval(cl)
# $foo
# [1] "bar"
deparse and substitute on ellipsis to get names of parameters
As a workaround try this
foo <- function(...) {
x <- substitute(...())
if(class(x[[1]]) == "call") sapply(x[[1]][-1] , deparse)
else sapply(x , deparse)
}
- Output
> foo(list(a, b))
[1] "a" "b"
> foo(a, b)
[1] "a" "b"
Get argument name instead of value in a function in R
We can use deparse/substitute
testFun <- function(x = a_vector) {
deparse(substitute(x))
}
testFun()
#[1] "a_vector"
R user-defined save load functions | Passing variable names as arguments using deparse(substitute)
You need to do the changes in both save
and load
functions. Use list
argument in save
function to save the data with the same variable names as passed value.
getSave <- function(folder, rdata){
val <- deparse(substitute(rdata))
save(list = val,
file = paste0("./", deparse(substitute(folder)), "/", val, ".RData"))
}
getSave(SData, x)
getSave(SData, y)
To load the data, specify the environment as global since by default the values are loaded in the called environment. Since you are loading the data in a function by default the values are loaded inside the function only.
getLoad <- function(folder, rdata){
load(paste0("./", deparse(substitute(folder)), "/", deparse(substitute(rdata)), ".RData"),
envir = .GlobalEnv)
}
getLoad(SData, x)
getLoad(SData, y)
So the issue was not related to deparse
, substitue
but how save
and load
functions work inside a user defined function.
deparse(substitute()) returns function name normally, but function code when called inside for loop
As soon as you use x
inside your function, it is evaluated, so it "stops being an (unevaluated) expression" and "starts being its resulting values (evaluated expression)". To prevent this, you must capture x
by substitute
before you use it for the first time.
The result of substitute
is an object which you can query as if it was a list. So you can use
x <- substitute(x)
and then x[[1]]
(the function name) and x[[2]]
and following (the arguments of the function)
So this works:
ds2 <- function(x) {
x <- substitute(x)
# you can do `x[[1]]` but you can't use the expression object x in a
# for loop. So you have to turn it into a list first
for (y in as.list(x)[-1]) {
print(deparse(y))
}
}
ds2(c(square,sum))
## [1] "square"
## [1] "sum"
How to get name of variable in R (substitute)?
I suggest you consider passing optional name value to these functions. I say this because it seems like you really want to use the name as a label for something in the end result; so it's not really the variable itself that matters so much as its name. You could do
fun1 <- function (some_variable, name=deparse(substitute(some_variable))) {
name
}
fun2 <- function (var_pass, name=deparse(substitute(var_pass))) {
fun1 (var_pass, name)
}
my_var <- c(1,2)
fun2(my_var)
# [1] "my_var"
fun1(my_var)
# [1] "my_var"
This way if you end up having some odd variable name and what to give a better name to a result, you at least have the option. And by default it should do what you want without having to require the name parameter.
Related Topics
Finding 2 & 3 Word Phrases Using R Tm Package
How to Call a Function Using the Character String of the Function Name in R
Speed Up Plot() Function for Large Dataset
R - Converting Date and Time Fields to Posixct with Hhmmss Format
Global Variables in Packages in R
How to Group My Date Variable into Month/Year in R
Writing Multiple Data Frames into .CSV Files Using R
Referring to Data.Table Columns by Names Saved in Variables
How to Insert an Image into the Navbar on a Shiny Navbarpage()
Using Stargazer with Rstudio and Knitr
Convert String to Date, Format: "Dd.Mm.Yyyy"
Extract Elements Common in All Column Groups
Setting Document Title in Rmarkdown from Parameters
How to Format Axis Labels with Exponents with Ggplot2 and Scales