在函数调用中使用deparse(substitute())后覆盖全局环境中的对象

时间:2018-12-20 18:46:34

标签: r

这是我在这里的处女作。因此,如果它不符合经验丰富的成员的高清晰度要求,请与我联系。

在我的全局环境中,我有4个对象(代表4年),这些对象是由12个数据框组成的列表(一年中每个月一个)。它们具有一致的结构,并且数据帧的列名称都相同。我试图使用一个函数一次更改所有4个列表中数据帧的这些列名,然后用具有新列名的数据帧的新对象覆盖全局环境中的所有4个对象

这是我的功能:

change.name <- function(data){
  for (i in 1:length(data)){
    names(data[[i]]) <- c("a", "b", "c", "d", "e")
  }
  assign(deparse(substitute(data)), value = data, envir = globalenv())
}

我使用我的函数:

change.name(my_object1)

它起作用,除了我得到以下警告消息:

  

警告信息:   在assign(deparse(substitute(data)))中,value = data,   envir = globalenv()):仅将第一个元素用作变量   名称

并且我的全局环境中的对象没有被覆盖。我得到一个名称如下的新对象:

  

“ list(Jan = structure(list(a = c(11,34,36,49,55,68,”

我知道这与在运行函数(或沿这些行的东西)时R创建的新环境中存储函数变量的方式有关。

我的问题很简单:我该如何解决?

3 个答案:

答案 0 :(得分:0)

好吧,问题出在function的行为方式上。看一下下面的代码,可能有帮助

testFun1 <- function (val) {
  a <<- val
  assign("b",a)
}
testFun2 <- function (val) {
  a <<- val
  assign("b",a, pos = 1)
}

# environment pretty much empty apart from our functions
ls()
[1] "testFun1" "testFun2"
# run
set.seed(123)
testFun1(runif(1))
# less empty
ls()
[1] "a"        "testFun1" "testFun2"
# still not quite it though
testFun2(runif(1))
# now that's better
ls()
[1] "a"        "b"        "testFun1" "testFun2"

有关更多信息,请查看文档(?assign),尤其是pos参数。

答案 1 :(得分:0)

您可以在执行deparse(substitute(data))之前使用data来解决此问题:

# Let's change your function just a bit
change.name <- function(data){
    # call deparse(substutite()) *before* you do anything to data
    object_name <- deparse(substitute(data))
    for (i in 1:length(data)){
        names(data[[i]]) <- c("a", "b", "c", "d", "e")
    }
    assign(object_name, value = data, envir = globalenv())
}

# Create sample data
my_object1 <- lapply(1:12, function(x) {
    data.frame(u = 1, v = 2, x = 3, y = 4, z = 5)
})
names(my_object1) <- month.name

change.name(my_object1)
ls()
#> [1] "change.name" "my_object1"
head(my_object1, 2)
#> $January
#>   a b c d e
#> 1 1 2 3 4 5
#> 
#> $February
#>   a b c d e
#> 1 1 2 3 4 5

reprex package(v0.2.1)于2018-12-20创建

答案 2 :(得分:0)

一种更惯用的(也许更安全)的方法来完成此任务可能是简单地使用lapplysetNames

my_object1 <- lapply(1:12, function(x) {
    data.frame(u = 1, v = 2, x = 3, y = 4, z = 5)
})
names(my_object1) <- month.name

change.name <- function(obj){
    lapply(obj,function(x) setNames(x,letters[1:5]))
}

my_object1 <- change.name(my_object1)