[R] Ensure parameter is a string when passed within an lapply & called function runs a 'substitute' on it

Bert Gunter bgunter.4567 at gmail.com
Tue May 10 21:55:54 CEST 2016


Andrew:

Actually, thinking about it a bit more, I think my "solution" is not
really a solution either; that is, it will fail in use. My
understanding, which may be wrong and which others may correct, is
this: in the lapply call, x.var = ... will result in substitute(...)
in testFunc yielding an unevaluated call with my eval() "solution".
The problem is: when this call gets evaluated in testFunc() **where**
does it get evaluated? The answer is: in the testFunc environment
(lexical scoping); if not found there in the parent of testFunc, which
is the environment in which testFunc **was defined**, not called, and
so on up through the tree of frames. My solution works only because I
stuck "var" in the global environment, which happened to be where
testFunc was defined. This will not be true in general, and almost
certainly will fail for your actual use case.

I see no clean solution for this issue -- it's the nature of lexical
scoping. A simple way to make it work is just to stick var in the
.GlobalEnv or baseenv(), depending on where the function with
substitute comes from (but probably the latter). Then var will be
found by lexical scoping. e.g., for your example:

vars <- names(dataSet)

lapply(vars, function(var) {
  # print(paste('var', var))
  assign("somename",var,globalenv())
  testFunc(x = model, pred.data = dataSet, x.var =
eval(somename,globalenv()), plot = F)
})

I would hope someone else may offer a better approach.


Cheers,
Bert

Bert Gunter

"The trouble with having an open mind is that people keep coming along
and sticking things into it."
-- Opus (aka Berkeley Breathed in his "Bloom County" comic strip )


On Tue, May 10, 2016 at 11:17 AM, Bert Gunter <bgunter.4567 at gmail.com> wrote:
> Well, here's a very bad way of doing this:
>
> vars <- names(dataSet)
>
> lapply(vars, function(var) {
>   assign("y",var,pos=parent.frame(2))
>   testFunc(x = model, pred.data = dataSet,
> x.var=eval(y,parent.frame(2)), plot = F)
> } )
>
> ## results in
>
> [1] "X1"
> [1] "X2"
> [1] "X3"
> [1] "X4"
> [1] "X5"
> [1] "X6"
> [[1]]
> [1] "X1"
>
> [[2]]
> [1] "X2"
>
> [[3]]
> [1] "X3"
>
> [[4]]
> [1] "X4"
>
> [[5]]
> [1] "X5"
>
> [[6]]
> [1] "X6"
>
>
> Assigning to the calling environment is a bad idea, but I have not
> figured out a better way to go about this.
>
>
> Cheers,
> Bert
> Bert Gunter
>
> "The trouble with having an open mind is that people keep coming along
> and sticking things into it."
> -- Opus (aka Berkeley Breathed in his "Bloom County" comic strip )
>
>
> On Mon, May 9, 2016 at 2:39 PM, Andrew Clancy <nite at achren.org> wrote:
>> Hi,
>>
>> I’m trying to solve what looks like the same issue as stack overflow article, but within an lapply:
>> http://stackoverflow.com/questions/18939254/cant-use-a-variable-as-an-argument-but-can-use-its-value
>>
>> I’ve replicated the issue with partialPlot below in ‘testFunc’. The lines up to the final print can’t change (including the substitute). In the first call it prints out ‘X1’ correctly, in the second it prints out ‘var’. I’ve tried eval, quote etc as the article suggests. Any ideas?
>>
>> numObs  <- 10
>> numVars <- 6
>> dataSet    <- data.frame(replicate(numVars,rnorm(numObs)))
>> # partialPlot(x = model, pred.data = dataSet, x.var = 'X1', plot = F)
>>
>> testFunc <- function(x, pred.data, x.var, plot=F) {
>>   x.var <- substitute(x.var)
>>   # print(paste('is.character(x.var)', is.character(x.var), 'is.name(x.var)', is.name(x.var)))
>>   xname <- if (is.character(x.var)) x.var else {
>>     if (is.name(x.var)) deparse(x.var) else {
>>       eval(x.var)
>>     }
>>   }
>>   print(xname)
>>   # print(head(pred.data[,xname]))
>> }
>>
>> vars <- names(dataSet)[[1]]
>> testFunc(x = model, pred.data = dataSet, x.var = local(vars), plot = F)
>>
>> lapply(vars, function(var) {
>>   # print(paste('var', var))
>>   testFunc(x = model, pred.data = dataSet, x.var = var, plot = F)
>> })
>>
>>         [[alternative HTML version deleted]]
>>
>> ______________________________________________
>> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see
>> https://stat.ethz.ch/mailman/listinfo/r-help
>> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
>> and provide commented, minimal, self-contained, reproducible code.



More information about the R-help mailing list