更新R中的数据框和环境

nic*_*las -5 r scoping

我不太清楚为什么数据框对象不会更新

d <- data.frame(titi=c(0))
(function(dataset) {
  dataset[["toto"]] <- 1;
  print(names(dataset)) #has "toto" and "titi"
})(d)
print(names(d)) # no has "toto", only "titi" 
Run Code Online (Sandbox Code Playgroud)

这里发生了什么 ?

我有一个解决方法,因为在我的代码中我也捕获变量并更新捕获的<<-,但我想知道机制.

我知道一般的变异等危险.我只是不明白这里的机制.

编辑

虽然这似乎是一个共识,这是一个语言级别的功能,我不遵循这个论点,好像我使用一个紧密的结构,数据表,它可以变异:

d <- data.table(titi=c(0))
(function(dataset) {
  dataset[,toto:=1]
  print(names(dataset)) #"titi" "toto"
})(d)
print(names(d)) #"titi" "toto"
Run Code Online (Sandbox Code Playgroud)

mne*_*nel 8

这里发生了什么?

您还没有阅读过R的介绍,特别是关于函数中的赋值部分或编写自己的函数的部分

两个相关的引用是

请注意,在函数内完成的任何普通赋值都是本地和临时的,并在退出函数后丢失.

表达式的值是为函数返回的值.

在你的情况下,函数调用的最终值names将返回一个字符向量....


范围界定可能是一个复杂的问题,但您的示例是一个简单的案例.

如果您想要更完整的参考,请查看R语言定义.


但是data.table它......

是的,:=data.table通过参考受让人.这不是普通的任务.

data.table继承自data.frame.它们不相同,并:=通过引用分配(也setattr)通过引用分配.这与标准R习语不符.这也可能导致问题,为什么data.table通过引用更新名称(DT),即使我分配给另一个变量?

还有其他方法,但标准的R习惯是函数中的普通赋值是本地的和临时的,并在退出后丢失.

你也可以考虑使用ReferenceClasses(见?setRefClass)


它不仅限于列表/ data.frames.原子载体是相同的

  mydf <- data.frame(a=1)
  mylist <- list(a=1)
  mynumeric <- c(a = 1)

mydf <- data.frame(a=1)
mylist <- list(a=1)
mynumeric <- c(a = 1)

foo <- function(x){x[['b']] <- 1; print(names(x))}

# data.frame
foo(mydf)
# [1] "a" "b"
mydf
#    a
#  1 1

# list
foo(mylist)
# [1] "a" "b"
mylist
# $a
# [1] 1

# atomic
foo(mynumeric)
# [1] "a" "b"
 mynumeric
# a 
#  1 
Run Code Online (Sandbox Code Playgroud)

  • 你的第二段可以从答案中删除而不影响其正确性...... (2认同)