2017-06-13 65 views
1

這看起來應該很簡單。我以爲我會做一個小時間表功能,以便我可以跟蹤工作中的時間。以下是代碼:數據幀不隨rbind變化

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") 

但是,數據幀保持不變而不會引發錯誤。這裏發生了什麼?

回答

1

原因在於作爲R詞法作用域和「環境」的概念作爲存儲空間:

「時間表」的對象是在全球環境聲明。然而,你的代碼試圖附加的「時間表」對象在「new.task」函數的範圍內聲明。所以「append」命令只是追加到本地的「時間表」中,而不是全局的。

爲了說明劃定範圍和環境下,我加入了一些提示性行代碼:

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") 

「pryr」庫加載獲得對象的內存地址。 當我們源代碼,第一:

  • 全球環境
  • 對象的全球環境
  • ,並在全球的「時間表」對象的內存地址列表的名稱/地址環境

被打印。

由於最後一行運行「new.task」函數,後來這三個信息被打印在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" 

爲了糾正這個問題,您應該superassign與「< < - 」(一個方法來修改存在於從另一個範圍的全球環境中的物體)操作如下:

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") 
+0

哇,是的,我的問題有幾個問題。我將rbind換成了append,並且改變了所有變量名,但是我很高興你看到了問題的根源。非常感謝你! – MokeEire