2016-08-03 4 views
8

わからないサブセット化されているデータフレームを変更%に%で使用されるには:R - サンプル私は完全に次の行動の理由を理解していないので、私が正しく質問を題した場合

dfSet <- data.frame(ID = sample(1:15, size = 15, replace = FALSE), va1 = NA, va3 = 0, stringsAsFactors = FALSE) 

dfSet[1:10, ]$va1 <- 'o1' 
dfSet[11:15, ]$va1 <- 'o2' 

dfSet[dfSet$ID %in% sample(dfSet[dfSet$va1 == 'o1', ]$ID, 7, replace = FALSE), ]$va3 <- 1 

print(length(unique(dfSet$ID))) 

私は最終的な印刷することを期待します15を示していますが、そうではありません。代わりに13または14が表示され、dfSetは途中で変更され、同じIDを持つ行が少なくとも2つ存在します。

dfSet[dfSet$ID %in% sample(dfSet[dfSet$va1 == 'o1', ]$ID, 7, replace = FALSE), ]$va3 <- 1 

変更する$ ID列 - 私はなぜわからないのですか?

回避策:すべてが期待通りに動作します。この場合

temp <- sample(dfSet[dfSet$va1 == 'o1', ]$ID, 7, replace = FALSE) 
dfSet[dfSet$ID %in% temp, ]$va3 <- 1 

- ユニークなIDを持つ15行があります。

なぜ%in%のサンプルを直接使用するのがデータフレームを変更するのでしょうか?

+1

"dfSet [dfSet $ ID%in%sample(dfSet [dfSet $ va1 == 'o1'、] $ ID、7、replace = FALSE)、" va3 "] < - 1 '。この問題は、答えを明確にするために苦労しているにもかかわらず、[< - 'と' $ < - 'の両方の評価にあるようです。 – MrFlick

+0

あなたの "回避策"はすべての場合に有効でしょうか?それとも、私はsthを知っている必要がありますか?私はあなたの解決策を大量に使うつもりです(それは1ライナーなので)、私はそれがOKであることを確認したいと思います。 –

+0

はい。 '[]'と '$'を '< - 'と組み合わせてはいけません。ただ一つだけをデータフレームで使用すれば安全です。 – MrFlick

答えて

7

を使用すると、戻り値を機能するように割り当てるときにRは、いくつかのトリッキーなことをやっていることです。たとえば、

a <- c(1,3) 
names(a) <- c("one", "three") 

のようなものは、ほとんどの言語で非常に奇妙に見えます。関数の戻り値にどのように値を代入しますか?実際には、names<-という名前の関数が定義されています。基本的には元のオブジェクトの変換されたバージョンを返すので、その関数に渡された値を置き換えることができます。したがって、実際には次のようになります

.temp. <- `names<-`(a, c("one","three")) 
a <- .temp. 

変数aは、その名前だけでなく、常に完全に置き換えられます。

あなたが本当に再び起こっている

dfSet$a<-1 

ような何かをするときは、両方の[]$サブセット化を実行しようとするとき

.temp. <- "$<-"(dfSet, a, 1) 
dfSet <- .temp. 

は今物事は少しトリッキー取得されます。このサンプルを見てください

#for subsetting 
f <- function(x,v) {print("testing"); x==v} 
x <- rep(0:1, length.out=nrow(dfSet)) 
dfSet$a <- 0 

dfSet[f(x,1),]$a<-1 

「テスト」が2回印刷されていることに注目してください。何が起こっているのは、だから、f(x,1)が二度評価され、より

.temp1. <- "$<-"(dfSet[f(x,1),], a, 1) 
.temp2. <- "[<-"(dfSet, f(x,1), , .temp1.) 
dfSet <- .temp2. 

本当に好きです。つまり、sampleも2回評価されます。

エラーがもう少し明らかであるあなたは列が追加として.temp1.変数ので、警告を取得し、現在は4列がありますが、時にまだ

ここ
dfSet[f(x,1),]$b<-1 
# Warning message: 
# In `[<-.data.frame`(`*tmp*`, f(x, 1), , value = list(ID = c(6L, : 
# provided 4 variables to replace 3 variables 

存在しない変数を交換しようとしています.temp2.への割り当てをしようとすると、置き換えようとしているデータフレームのスライスが異なるサイズになってしまうという問題があります。

$<-演算子が新しい列を返すだけでなく、割り当てられた値に更新された列を持つ新しいdata.frameを返すため、IDが置き換えられます。これは、割り当てが発生したときにそこにあったIDとともに更新された行が返されることを意味します。これは.temp1.変数に保存されます。次に、[<-割り当てを実行するときに、新しいスワップセットを選択しています。これらの行のすべての列の値は、.temp1.の値に置き換えられます。これは、置き換えられた行のIDを上書きすることになり、異なる場合があるため、指定されたIDの2つ以上のコピーを作成する可能性があることを意味します。

+0

この例の 'ID'カラムは上書きされますか? –

+0

@C_Z_その質問に具体的に対処する段落を追加しようとしました – MrFlick

+0

' trace(f) 'は' trace(sample) 'と同様に2つの評価を表示します。サンプルは実際に2回評価されます –

2

私は100%確信していませんが、Rはsampleを2回実行していると思われます。あなたはサブセットRに割り当てた場合、例えば:

x[i:j,]$v1 <- 1 

それは「一時的なデータフレームとしてxからjに私を行を取り出し、そのデータフレームのv1の列に1を代入し、次にコピーとして評価されます一時的なデータフレームをxの行iからjに戻します。

索引付け式(i:j)は2回実行されます(1回抽出すると1回戻す)。ランダム変数の場合、結果は元のものとは異なる行に戻されます選択された。

+0

本当に、 '$ < - data.frame"と '[< - 。data.frame"の両方が(この順番で)呼び出されているので、MrFlickノートのように、最初に、保存されていないオブジェクト( 'x [i:j、]')は '' $ < - ''に渡され、その "v1"列は "1"に割り当てられ、 data.frame "_as a whole_は[[ - ]'に渡され、 'x [i:j、]'に代入されるので、 'i:j'は部分集合引数として2回評価されます。 –

1

この単純な例で考えてみましょう:どのような二行目が実際にはあなたが$<-だけの3つの引数を取る関数、 オブジェクト、名前であることがわかります

x <- `$<-`(x, 'b', 5) 

ある

x <- data.frame(a=1:10, b=10:1) 
x$b <- 5 

をと値。 (あなたが直接$<-を使用したい場合はバッククォートが必要であることに注意してください。)

私はあなたの例xに が原因 sampleへの呼び出しに、別のものにそれが評価されるたびに評価される式があるということだと思う問題をので、これを避ける必要があります。

代替は明らかに、この問題はありませんどの[<-を使用することです:問題のようです何

dfSet[dfSet$ID %in% sample(dfSet[dfSet$va1 == 'o1', ]$ID, 7, replace = FALSE), 'va3'] <- 1 
関連する問題