質問: お世話になります。初歩的な質問で恐縮ですが、大きなデータを扱う上で計算時間が掛かり過ぎる問題が解決できずにいるのでアドバイスいただけたら幸いです。 やりたいこととしては、 ``` v <- c(1,5,10,1,2,4) names(v) <- c("a1_b1","a1_b8","a2_b3","a3_b1","a3_b2","a4_b7") library(Matrix) mat <- Matrix(0,nrow=4,ncol=8) rownames(mat) <- paste("a",seq(1,4),sep="") colnames(mat) <- paste("b",seq(1,8),sep="") ``` このベクトルvを疎行列matにマッピングしたいと考えています。ほしい結果は ``` b1 b2 b3 b4 b5 b6 b7 b8 a1 1 . . . . . . 5 a2 . . 10 . . . . . a3 1 2 . . . . . . a4 . . . . . . 4 . ``` のような行列です。 当初は 1 forループでa1~a4まで繰り返し操作 2 i=1のときvの中からa1に相当する要素(この場合はc(1,5))を抽出 3 要素数8、値0の空のベクトルX(添字b1~b8)を作成し、2で取得した要素を対応する添字(今回はb1,b8)にマッピング 4 XをdgCMatrixに変換 5 2〜4をi=4まで繰り返す、作成したXは順次rowbindしていく という手法を取っていましたが、データサイズが大きくなると現実的な時間では終わりません(実際はvは5000万要素あります)。 2の部分(抽出)に多くの時間がかかっているようなので、for文ではなくapplyなどでまとめて処理したいと考えていますがアイデアが思いつきません。 わかりにくい文章で恐縮ですがお助けいただければ嬉しいです。
回答: 行列 (配列) のインデックスには1列目に行の値,2列目に列の値を持つ行列を与えることができます. これを利用すると `for` を使わず,一括して値を代入できるので高速化すると思います. ベクトル v の名前からインデックスを作成するところが若干面倒ですが,以下のコードでいけるはずです. ``` library(stringr) i <- names(v) %>% str_replace_all(c(a = "", b = "")) %>% str_split("_") %>% unlist %>% as.integer %>% matrix(ncol = 2, byrow = TRUE) mat[i] <- v mat ```