文字列変数からのダミー変数 質問する

文字列変数からのダミー変数 質問する

このデータセットからダミー変数を作成したいと思います。

DF<-structure(list(A = c(1, 2, 3, 4, 5), B = c("1,3,2", "2,1,3,6", 
  "3,2,5,1,7", "3,7,4,2,6,5", "4,10,7,3,5,6")), .Names = c("A", "B"), 
              row.names = c(NA, 5L), class = "data.frame")
> DF
  A                  B
1 1              1,3,2
2 2            2,1,3,6
3 3          3,2,5,1,7
4 4        3,7,4,2,6,5
5 5       4,10,7,3,5,6

望ましい出力は次のようになります。

A  1  2  3  4  5  6  7  8  9  10
1  1  1  1  0  0  0  0  0  0  0
2  1  1  1  0  0  1  0  0  0  0
3  1  1  1  0  1  0  1  0  0  0
4  0  1  1  1  1  1  1  0  0  0
5  0  0  1  1  1  1  1  0  0  1

strsplitこのようなことを効率的に行う方法はありますか?または を使用できますifelse。元のデータセットは非常に大きく、行数が多く (>10k)、列 B に値 (>15k) があります。dummyパッケージの関数dummiesは期待どおりに動作しません。

同様のケースも見つかりました:1つの列を複数の列に分割するしかし、私のケースでは、上記のリンクからの回答は非常に遅くなります (Dell i7-2630QM、8Gb、Win7 64 ビット、R 2.15.3 64 ビットで最大 15 分)。

ご回答をよろしくお願いいたします。

ベストアンサー1

アップデート

ここで言及した関数は、現在 CRAN で入手可能な「splitstackshape」というパッケージに移動されています。CRAN のバージョンは、この元のバージョンよりもかなり高速です。速度は、forこの回答の最後に記載されている直接ループ ソリューションで得られる速度とほぼ同じになるはずです。詳細なベンチマークについては、@Ricardo の回答を参照してください。

インストールして使用し、concat.split.expanded目的の結果を得ます。

library(splitstackshape)
concat.split.expanded(DF, "B", fill = 0, drop = TRUE)
#   A B_01 B_02 B_03 B_04 B_05 B_06 B_07 B_08 B_09 B_10
# 1 1    1    1    1    0    0    0    0    0    0    0
# 2 2    1    1    1    0    0    1    0    0    0    0
# 3 3    1    1    1    0    1    0    1    0    0    0
# 4 4    0    1    1    1    1    1    1    0    0    0
# 5 5    0    0    1    1    1    1    1    0    0    1

元の投稿

以前、私はこの種の分割だけでなく、他の分割も行う関数を書きました。 という関数はconcat.split()ここ

サンプルデータの使用法は次のようになります。

## Keeping the original column
concat.split(DF, "B", structure="expanded")
#   A            B B_1 B_2 B_3 B_4 B_5 B_6 B_7 B_8 B_9 B_10
# 1 1        1,3,2   1   1   1  NA  NA  NA  NA  NA  NA   NA
# 2 2      2,1,3,6   1   1   1  NA  NA   1  NA  NA  NA   NA
# 3 3    3,2,5,1,7   1   1   1  NA   1  NA   1  NA  NA   NA
# 4 4  3,7,4,2,6,5  NA   1   1   1   1   1   1  NA  NA   NA
# 5 5 4,10,7,3,5,6  NA  NA   1   1   1   1   1  NA  NA    1

## Dropping the original column
concat.split(DF, "B", structure="expanded", drop.col=TRUE)
#   A B_1 B_2 B_3 B_4 B_5 B_6 B_7 B_8 B_9 B_10
# 1 1   1   1   1  NA  NA  NA  NA  NA  NA   NA
# 2 2   1   1   1  NA  NA   1  NA  NA  NA   NA
# 3 3   1   1   1  NA   1  NA   1  NA  NA   NA
# 4 4  NA   1   1   1   1   1   1  NA  NA   NA
# 5 5  NA  NA   1   1   1   1   1  NA  NA    1

NA を 0 に再コーディングするには手動で行う必要があります。おそらく関数を更新してオプションを追加し、同時にこれらのより高速なソリューションの 1 つを実装するでしょう :)

temp <- concat.split(DF, "B", structure="expanded", drop.col=TRUE)
temp[is.na(temp)] <- 0
temp
#   A B_1 B_2 B_3 B_4 B_5 B_6 B_7 B_8 B_9 B_10
# 1 1   1   1   1   0   0   0   0   0   0    0
# 2 2   1   1   1   0   0   1   0   0   0    0
# 3 3   1   1   1   0   1   0   1   0   0    0
# 4 4   0   1   1   1   1   1   1   0   0    0
# 5 5   0   0   1   1   1   1   1   0   0    1

アップデート

関数のオーバーヘッドのほとんどは、からconcat.splitへの変換や列名の変更などによるものと思われます。分割を行うために実際に使用されるコードは、matrixdata.frameガスッ forループしますが、テストしてみると、パフォーマンスがかなり良いことがわかります。

b = strsplit(DF$B, ",")
ncol = max(as.numeric(unlist(b)))
temp = lapply(b, as.numeric)
## Set up an empty matrix
m = matrix(0, nrow = nrow(DF), ncol = ncol)      
## Fill it in
for (i in 1:nrow(DF)) {
  m[i, temp[[i]]] = 1
}
## View your result
m 

おすすめ記事