这看起来应该很简单。我想我会做一个小时间表功能,这样我就可以跟踪我的工作时间。以下是代码:
timesheet <- data.frame(matrix(nrow = 0, ncol = 3))
varn <- c("date", "project", "status")
colnames(timesheet) <- varn
timesheet[1,] <- c(date(), "test", "test")
#The above line exists because rbind was renaming the columns otherwise
new.task <- function(project){
timesheet <- append(time, c(date(), project, "started"))
}
new.task("Name of task")
但是数据框保持不变而不会抛出错误。这是怎么回事?
答案 0 :(得分:1)
原因在于词汇范围的概念和&#34;环境&#34;在R中作为存储空间:
&#34;时间表&#34;对象在全球环境中声明。但是&#34;时间表&#34;您的代码尝试追加的对象是在&#34; new.task&#34;范围内声明的。功能。所以&#34;追加&#34;命令只是附加到本地&#34;时间表&#34;而不是全局的。
为了说明范围和环境,我在您的代码中添加了一些信息行:
library(pryr)
timesheet <- data.frame(matrix(nrow = 0, ncol = 3))
varn <- c("date", "project", "status")
colnames(timesheet) <- varn
timesheet[1,] <- c(date(), "test", "test")
#The above line exists because rbind was renaming the columns otherwise
print(environment())
print(ls(environment()))
sprintf("address of timesheet object is %s", pryr::address(timesheet))
new.task <- function(project){
timesheet <- append(time, c(date(), project, "started"))
print(environment())
print(ls(environment()))
sprintf("address of timesheet object is %s", pryr::address(timesheet))
}
new.task("Name of task")
&#34; pryr&#34;加载库以获取对象的内存地址。 当我们获取代码时,首先:
。
由于最后一行运行&#34; new.task&#34;函数,后来三个信息都在new.task函数中打印。看到差异:
<environment: R_GlobalEnv>
[1] "new.task" "timesheet" "varn"
[1] "address of timesheet object is 0x365b8e8"
<environment: 0x32ef750>
[1] "project" "timesheet"
[1] "address of timesheet object is 0x365dbb8"
为了纠正这个问题,你应该使用&#34;&lt;&lt; - &#34;来超级签名(一种修改全局环境中存在的对象的方法)。运算符如下:
new.task <- function(project){
timesheet <<- append(time, c(date(), project, "started"))
}
但您的代码中还有两个错误:
所以正确的形式应该是这样的(你也可以使用rbind):
timesheet[nrow(timesheet)+1,] <<- c(date(), project, "started")
另一种修改没有超级赋值运算符的全局对象的方法是用它的环境引用它,如下所示:
timesheet <- data.frame(matrix(nrow = 0, ncol = 3))
varn <- c("date", "project", "status")
colnames(timesheet) <- varn
timesheet[1,] <- c(date(), "test", "test")
#The above line exists because rbind was renaming the columns otherwise
envg <- environment()
new.task <- function(project, env = envg){
env$timesheet[nrow(env$timesheet)+1,] <- c(date(), project, "started")
}
new.task("Name of task")