2017-06-13 5 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"関数のスコープ内で宣言されます。したがって、「追加」コマンドは、グローバルなものではなく、ローカルの「タイムシート」に追加するだけです。スコーピングや環境を説明するために

、私はあなたのコードにいくつかのinformatoryの行を追加しました:

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"関数を実行するので、後で3つの情報が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")) 
} 

しかし、あなたのコード内の2つのエラーがある:

  • は、あなたが自分自身で「時間」ではないタイムシート、および「時間」に追加しようと、閉鎖、ビルトインFUNCTですイオン。
  • ベクトルまたはリストに追加します。しかし、データフレームに追加しようとすると、それがリストに変換されます。

だから、正しいフォームでは、この(あなたにもrbind使用することができます)のようにする必要があります:

timesheet[nrow(timesheet)+1,] <<- c(date(), project, "started") 

そしてsuperassignmentオペレータなしでグローバルオブジェクトを修正する別の方法は、のように、その環境でそれを参照することです次のようになります。

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を切り替えて、1つの変数名以外はすべて変更しましたが、問題の根本を見てうれしいです。どうもありがとうございました! – MokeEire

関連する問題