base
のorder()
内部で仕様されいているxtfrm()
の仕様の変更で、order()
関数がデータフレームをうけつけなくなった(バージョン4.2.xまでは受け付けていた)。
どういうことかと言うと、以前はデータフレームを特定の列の昇順(または降順)で変えようと思ったときに次のようなコードも以前のバージョンのRでは実行可能だったが現在は実行できなくなっている。
# 例えば、irisデータをSepal.Lengthの昇順で並び替えてみようと思った場合(現在はエラーで実行できない) iris[order(iris["Sepal.Length"]), ]
## Error in xtfrm.data.frame(x): cannot xtfrm data frames
もちろん、ベクトルとして$
を使って列を呼び出せば従来どおり実行可能となる。
head(iris[order(iris$Sepal.Length), ])
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 14 4.3 3.0 1.1 0.1 setosa
## 9 4.4 2.9 1.4 0.2 setosa
## 39 4.4 3.0 1.3 0.2 setosa
## 43 4.4 3.2 1.3 0.2 setosa
## 42 4.5 2.3 1.3 0.3 setosa
## 4 4.6 3.1 1.5 0.2 setosa
どうしてもデータフレームの状態で呼び出したければdo.call
や(unlist()
)などはさんでやるといい。
head(iris[do.call(order, iris["Sepal.Length"]), ])
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 14 4.3 3.0 1.1 0.1 setosa
## 9 4.4 2.9 1.4 0.2 setosa
## 39 4.4 3.0 1.3 0.2 setosa
## 43 4.4 3.2 1.3 0.2 setosa
## 42 4.5 2.3 1.3 0.3 setosa
## 4 4.6 3.1 1.5 0.2 setosa
head(iris[order(unlist(iris["Sepal.Length"])), ])
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 14 4.3 3.0 1.1 0.1 setosa
## 9 4.4 2.9 1.4 0.2 setosa
## 39 4.4 3.0 1.3 0.2 setosa
## 43 4.4 3.2 1.3 0.2 setosa
## 42 4.5 2.3 1.3 0.3 setosa
## 4 4.6 3.1 1.5 0.2 setosa
ここで問題になるのが、データの行を昇順に並び替えたいと思ったとき。例えば次のようなデータセットを考えてみる。
set.seed(123) d <- data.frame(ID = 1:10, TIEM_01 = rnorm(10), TIME_02 = rnorm(10), TIME_03 = c(rnorm(5), NA, rnorm(3), NA)) d
## ID TIEM_01 TIME_02 TIME_03
## 1 1 -0.56047565 1.2240818 -1.0678237
## 2 2 -0.23017749 0.3598138 -0.2179749
## 3 3 1.55870831 0.4007715 -1.0260044
## 4 4 0.07050839 0.1106827 -0.7288912
## 5 5 0.12928774 -0.5558411 -0.6250393
## 6 6 1.71506499 1.7869131 NA
## 7 7 0.46091621 0.4978505 -1.6866933
## 8 8 -1.26506123 -1.9666172 0.8377870
## 9 9 -0.68685285 0.7013559 0.1533731
## 10 10 -0.44566197 -0.4727914 NA
このデータセットは本来は各行ごとに昇順に並んでいるはずだが、データの取り方(webからのスクレイピングなど)の都合から昇順に並んでいないものと考える。ここで以前ならば、各行のデータを昇順に並び替える方法としては次のようにするとよかった。
for(i in 1:nrow(d)) d[i, 2:4] <- d[i, 2:4][order(d[i, 2:4])]
## Error in xtfrm.data.frame(x): cannot xtfrm data frames
今回は残念ながらdo.call()
ではうまくいかない。ここではunlist()
をつかって、取り出した行の値をベクトル化すると意図した通り動く。
for(i in 1:nrow(d)) d[i, 2:4] <- d[i, 2:4][order(unlist(d[i, 2:4]))] d
## ID TIEM_01 TIME_02 TIME_03
## 1 1 -1.0678237 -0.56047565 1.2240818
## 2 2 -0.2301775 -0.21797491 0.3598138
## 3 3 -1.0260044 0.40077145 1.5587083
## 4 4 -0.7288912 0.07050839 0.1106827
## 5 5 -0.6250393 -0.55584113 0.1292877
## 6 6 1.7150650 1.78691314 NA
## 7 7 -1.6866933 0.46091621 0.4978505
## 8 8 -1.9666172 -1.26506123 0.8377870
## 9 9 -0.6868529 0.15337312 0.7013559
## 10 10 -0.4727914 -0.44566197 NA
ちょっとバッドノウハウ感があるのでもう少しいい解決策があるのかもしれない。
たしかにorder()
関数が二列以上のデータフレームを指定した場合の挙動は謎挙動だったので、エラーになるのもやむを得ないかもしえれないが、前に書いたコードを久々に動かしたらエラーを吐いてびっくりした。結構大きな変更だと思うが、NEWSにそれっぽい記述が見つけられなかった。