44

偶然、"[<-"オペレーターの奇妙な振る舞いに遭遇しました。呼び出しの順序と、RStudio を使用しているか、通常の RGui を使用しているかによって、動作が異なります。例を挙げて自分自身を明確にします。

x <- 1:10
"[<-"(x, 1, 111)
x[5] <- 123

私の知る限り、最初の代入は変更すべきではありませんx(または、私が間違っているのでしょうか?) が、2 番目の代入は変更する必要があります。実際、上記の操作の結果は

x
[1]  1  2  3  4  123  6  7  8  9 10

ただし、これらの操作を異なる順序で実行すると、結果が異なり、x変更されました。意味:

x <- 1:10
x[5] <- 123
"[<-"(x, 1, 111)
x
[1] 111   2   3   4   123   6   7   8   9  10

しかし、それはプレーンRを使用している場合にのみ発生します! RStudio では、動作は両方のオプションで同じです。2 台のマシン (1 つは Fedora を搭載し、もう 1 つは Win7 を搭載) で確認しましたが、状況はまったく同じように見えます。「機能」バージョン ( "[<-"(x..)) はおそらく使用されないことはわかっていますが、なぜそれが起こっているのか非常に興味があります。誰かがそれを説明できますか?

==========================

編集: わかりましたので、コメントから、理由はx <- 1:10「整数」型であり、置換後はx[5] <- 123「倍精度」であることがわかりました。しかし、なぜ RStudio で動作が異なるのかという疑問が残ります。R セッションを再起動しても何も変わりません。

4

1 に答える 1

37

Rstudioの振る舞い

Rstudio のオブジェクト ブラウザは、変更時にコピーを強制する方法で検査対象のオブジェクトを変更します。具体的には、オブジェクト ブラウザは、オブジェクトの名前付きフィールドの値を 1 から 2にリセットするプロセスで、その呼び出しが内部的にオブジェクトの評価を強制する少なくとも 1 つの R 関数を採用しています。R-Internals マニュアルから:

オブジェクトが変更される直前に、名前付きフィールドが参照されます。値 2 は、オブジェクトを変更する前に複製する必要があることを意味します。[...] 値 1 は状況に使用されます [...] 原則として、計算中に a の 2 つのコピーが存在します [...] しかし、それ以上存在しないため、一部のプリミティブ関数を最適化できますこの場合、コピーを避けるために。

オブジェクト ブラウザーが名前付きフィールド ([NAM()]次のコード ブロック内) を変更することを確認するには、次の行を実行した結果を比較します。最初に、両方の「行」が一緒に実行されるため、Rstudio はXその構造が照会される前に「触れる」時間がありません。2 番目の例では、各行が個別に貼り付けられているため、X検査前に変更されています。

## Pasted in together
x <- 1:10; .Internal(inspect(x))
# @46b47b8 13 INTSXP g0c4 [NAM(1)] (len=10, tl=0) 1,2,3,4,5,...

## Pasted in with some delay between lines
x <- 1:10
.Internal(inspect(x))
# @42111b8 13 INTSXP g0c4 [NAM(2)] (len=10, tl=0) 1,2,3,4,5,... 

名前付きフィールドが 2 に設定されると、[<-(X, ...)元のオブジェクトは変更されません。以下を一度に Rstudio に貼り付けると が変更されますがX、行ごとに貼り付けても変更されません。

x <- 1:10
"[<-"(x, 1, 111)

このすべてのもう 1 つの結果は、Rstudio のオブジェクト ブラウザーが実際に一部の操作を他の場合よりも遅くすることです。もう一度、最初に一緒に貼り付けた同じ 2 つのコマンドを比較し、次に 1 つずつ比較します。

## Pasted in together
x <- 1:5e7
system.time(x[1] <- 9L)
#    user  system elapsed 
#       0       0       0 

## Pasted in one at a time
x <- 1:5e7
system.time(x[1] <- 9L)
#    user  system elapsed 
#    0.11    0.04    0.16 

[<- R における変数の振る舞い

[<-ベクトルを変更する wrtの動作は、それに割り当てられる要素Xのストレージ タイプによって異なります。Xこれは の動作を説明してRいますが、Rstudio の動作は説明していません。

R では[<-、 vector に追加するか、の型を変更Xする必要がある部分代入を実行すると、がコピーされ、返される値は既存の variable を上書きしません。(そのためには、 のようなことをする必要があります。XXXX <- "[<-(X, 2, 100)

したがって、次のいずれも X を変更しません

X <- 1:2         ## Note: typeof(X) --> "integer"

## Subassignment that requires that X be coerced to "numeric" type
"[<-"(X, 2, 100) ## Note: typeof(100) --> "numeric"
X 
# [1]   1   2

## Appending to X
"[<-"(X, 3, 100L)
X
# [1]   1   2

ただし、R では可能な限り、参照によって関数を直接 (つまり、コピーを作成せずに)[<-変更することを許可しています。ここでの「可能性」には、サブ割り当てでそのタイプを変更Xする必要がない場合が含まれます。X

したがって、次のすべては X を変更します

X <- c(0i, 0i, 0i, 0i)
"[<-"(X, 1, TRUE)
"[<-"(X, 2, 20L)
"[<-"(X, 3, 3.14)
"[<-"(X, 4, 5+5i)
X
# [1]  1.00+0i 20.00+0i  3.14+0i  5.00+5i
于 2013-03-21T23:17:07.687 に答える