10

次のデータ フレームを検討してください。

TEST <- structure(list(Value = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), 
  Select = structure(c(2L, 1L, 3L, 2L, 2L, 1L, 1L,
  2L, 1L, 1L, 3L, 3L), .Label = c("A", "B", "C"), class = "factor"),
  A = c(5L, 5L, 4L, 3L, 4L, 3L, 5L, 3L, 3L, 4L, 5L, 4L), 
  B = c(10L, 8L, 7L, 6L, 3L, 8L, 8L, 7L, 8L, 9L, 11L, 8L), 
  C = c(0L, 1L, 3L, 2L, 0L, 3L, 0L, 2L, 0L, 1L, 1L, 0L)), 
  .Names = c("Value", "Select", "A", "B", "C"), 
  row.names = c(NA, -12L), 
  class = "data.frame")

Select列に基づいて、列A、B、およびCのセットから、行ごとにValue列を効率的に割り当てたいと考えています。

たとえば、行 1 では、Value を列 B の要素と等しくする必要があります。つまり、Value[1]=10 です。

私の現在の方法は、for ループを使用することです。

for( idx in 1:nrow(TEST) ) {
  TEST$Value[idx] <- TEST[ idx, as.character(TEST$Select[idx]) ]
}

これにより、目的の出力が得られます。

    値選択 ABC
 1 10 B 5 10 0
 2 5 あ 5 8 1
 3 3 C 4 7 3
 4 6 B 3 6 2
 5 3 B 4 3 0
 6 3 A 3 8 3
 7 5 あ 5 8 0
 8 7 B 3 7 2
 9 3 A 3 8 0
 10 4 あ 4 9 1
 11 1 C 5 11 1
 12 0 C 4 8 0

これを行うためのより効率的な方法または代替方法はありますか? これは、ある種のmerge()またはテーブル結合タイプの操作のように感じます。

PS この操作を説明する方法がよくわかりませんでした。より良い質問/説明の提案も歓迎します。

4

1 に答える 1

10

マトリックス インデックスとを使用しmatchます。forそのアプローチはベクトル化されているため、 orループよりもはるかに高速applyです。

L <- c("A", "B", "C")
TEST$Value <- TEST[L][cbind(seq_len(nrow(TEST)), match(TEST$Select, L))]

マトリックスのインデックス付けに慣れていない場合は、次のドキュメントに記載されています?"["

インデックス付けの 3 番目の形式は、各次元に 1 列の数値行列を使用するものです。インデックス行列の各行は配列の 1 つの要素を選択し、結果はベクトルになります。

于 2013-08-05T11:21:51.630 に答える