简体   繁体   中英

Issue with using get() in R - object is not found (might be related to environment?)

after learning so much by searching for answers on Stack OverFlow, I'm sharing my first question in the hope someone can help me. In the end, I plan to write a more complex function but I already condensed it to this issue, which I think is related to variable allocation / variable environment in R.

What I try to do, basically, is to set a variable name based on a string, so I can pass it over to the function (and use it as a parameter in another subordinate function). Therefore, I try to use the get() function. However, in the end, I always get the Error in get(xyz): object 'xyz' not found . I feel like the solution shouldn't be that difficult and that I miss something obvious, but after various attempts described below, I'm stuck.

But let's start from the beginning. This is what I want to do and it works fine when used in the Console/ Global Environment (please keep in mind, that this is a condensed version, I obviously wouldn't create a function just for that):

lapply(mi.list, FUN = function(dat) {
    xyzabc <- "WeightResp_BL_Full"
    stats::lm(Burden_Amount_BL ~ Akzeptanz_3_BL_r, data = dat, weight=get(xyzabc))
})
[Correct Output]

I am also able to recreate the same functionality when I hard-write it into the function like this:

condensed_f <- function (mi.list, formula) 
{   lapply(mi.list, FUN = function(dat) {
        stats::lm(formula, data = dat, weight=get("WeightResp_BL_Full"))
    })}
condensed_f (mi.list=mi.list, formula="Burden_Amount_BL ~ Akzeptanz_3_BL_r")
[Correct Output]

However, when I try to assign the string to a variable and use get(xyz) , I get the error message that the object 'xyz' [is] not found :

condensed_f <- function (mi.list, formula) 
{   lapply(mi.list, FUN = function(dat) {
        xyz <- "WeightResp_BL_Full"
        print(xyz)
        stats::lm(formula, data = dat, weight=get(xyz))
    })}
condensed_f (mi.list=mi.list, formula="Burden_Amount_BL ~ Akzeptanz_3_BL_r")

[1] "WeightResp_BL_Full"
 Error in get(xyz) : object 'xyz' not found 

As you can see through the printout, xyz is accessible there, yet it isn't able to be found when used in the lm() -function. At the same time, however, there is no issue with the formula variable.

The issue persists when I define xyz in the same way I define formula :

condensed_f <- function (mi.list, formula, xyz="WeightResp_BL_Full") 
{   lapply(mi.list, FUN = function(dat) {
        print(xyz)
        stats::lm(formula, data = dat, weight=get(xyz))
    })}
condensed_f (mi.list=mi.list, formula="Burden_Amount_BL ~ Akzeptanz_3_BL_r")

[1] "WeightResp_BL_Full"
 Error in get(xyz) : object 'xyz' not found 

condensed_f <- function (mi.list, formula, xyz) 
{   lapply(mi.list, FUN = function(dat) {
        print(xyz)
        stats::lm(formula, data = dat, weight=get(xyz))
    })}
condensed_f (mi.list=mi.list, formula="Burden_Amount_BL ~ Akzeptanz_3_BL_r", xyz="WeightResp_BL_Full")

[1] "WeightResp_BL_Full"
 Error in get(xyz) : object 'xyz' not found 

I, therefore, tried to debug it and went step-by-step into the underlying functions. What I discovered is, that formula is used relatively early after lm() is called, whereas the weight -parameter is used later. That's why I presume that this might be related to the environment where R searches for the xyz object, So I played around with the envir parameter: get(xyz, envir=environment()) and get(xyz, envir=parent.env()) , yet the same issue persisted.

Maybe it isn't even related to the environment and using the get() function is the wrong way to go here. I also tried to resolve the string with eval(parse(xyz)) but wasn't having any luck there.

Maybe someone out there sees this is finds the (obvious?) solution? I would really appreciate the help.

Edit1 : I realized that it might be helpful to clarify the structure of mi.list and its related variables. I have a dataset of several hundred people containing, among others's the variables Burden_Amount_BL , Akzeptanz_3_BL_r , and WeightResp_BL_Full .

A condensed overview would look like this:

condensed_dataset

       id Burden_Amount_BL        Akzeptanz_3_BL_r WeightResp_BL_Full
1    8371               NA Definitely will not use          1.1279761
2    4824                4     Definitely will use          0.9129661
3    5146                3                      NA          0.8846529
4   57169                3 Definitely will not use          1.5682342
5   12479                3   Probably will not use          0.3589912
6    3489                3                      NA          1.1799084
7      37                3   Probably will not use          1.2451010
8    9634               NA          Maybe will use          1.1470681
9     278                0   Probably will not use          1.2789439
10  84691                2 Definitely will not use          1.6766708

As there is missing data, I use MICE to impute it, leaving me with the imputed dataset object. (This is just exemplary, the real imputation is more complex and uses a much bigger dataset and a pre-specified predictor-matrix).

condensed_imp <- mice(condensed_dataset,m=10, maxit=10)

As I want to calculate an ANOVA with the imputed data, I could use mi.anova(mi.res=imp, formula="Burden_Amount_BL ~ Akzeptanz_3_BL_r") . As mi.anova() however, does not offer the ability to specify weights, I tried to create my own version and adapt it where needed, which lead me to the problem described above. The specific steps that are performed before using the lapply() would be these, basically creating a list of imputed data frames:

class(condensed_imp)
[1] "mids"
m <- condensed_imp$m
h1 <- list(rep("", m))
for (ii in 1:m) {
    h1[[ii]] <- as.data.frame(mice::complete(condensed_imp, 
        ii))
}
mi.list <- h1

Works here:


condensed_f <- function (mi.list, formula, xyz = "WeightResp_BL_Full")  {
    lapply(mi.list, FUN = function(dat) {
        ## print(xyz)
        x <- rnorm(10)
        y <- rnorm(10)
        stats::lm( y~x, weight=get(xyz) )
        ## stats::lm(formula, data = dat, weight=get(xyz))
    })
}

mi.list <- list(1,2,3)
WeightResp_BL_Full <- runif(10)
foo <- condensed_f (mi.list=mi.list, formula="Burden_Amount_BL ~ Akzeptanz_3_BL_r")

stopifnot( length(foo) == 3 )

Could you showcase actually setting the WeightResp... variable to something? (though I doubt that explains it)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM