【问题标题】:Overwriting an object in the global environment after using deparse(substitute()) in a function call在函数调用中使用 deparse(substitute()) 后覆盖全局环境中的对象
【发布时间】:2019-05-21 07:30:07
【问题描述】:

这是我在这里的第一篇文章。因此,如果它不符合更多经验丰富的成员的高清晰度标准,请多多包涵。

我的全球环境中有 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 = 结构(list(a = c(11, 34, 36, 49, 55, 68, "

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

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

【问题讨论】:

  • 这是完成此任务的一种非常不寻常的方法(更改数据帧集合上的列名)。是否有特定原因让您觉得必须使用 assigndeparse 等?

标签: r


【解决方案1】:

处理此任务的更惯用(并且可能更安全)的方法可能是简单地使用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)

【讨论】:

  • 谢谢。这似乎没有我的代码那么复杂。我是一个相对新手,所以我很高兴有人向我展示如何更优雅地实现目标。
【解决方案2】:

你可以通过使用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 日创建

【讨论】:

  • 谢谢一百万。它完全按照我的意愿工作。还有这么简单的解决方案。谢谢。
  • 没问题,很高兴它有帮助。干杯!
【解决方案3】:

没错,问题在于functions 的行为方式。看看下面的代码,可能会有所帮助

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 参数。

【讨论】:

    猜你喜欢
    • 2013-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-04
    • 2019-12-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多