2011-02-09 14 views
2

bigsplit()操作の結果リスト(bigmalyoryパッケージ、bigmemoryパッケージの一部)の一覧があります。lapplyを使わずにリストのリストをRのスパース行列にするには?

各リストは、マトリックス内の列を表し、各リスト項目は、バイナリマトリックス内の値1へのインデックスです。

このリストをスパースバイナリ(0/1)マトリックスにする最も良い方法は何ですか? lapply()内のlapply()のみを使用していますか?列の名前としてリストの名前を付ける要因を保持するにはどうすればよいですか?

+0

です。あなたはリストを持っています(col1 = list(1,4)、col2 = list(2,6,8)、そういうものですか? –

+0

私は非常に反応が遅かったですが、あなたの答えは素晴らしかったです。 – Ron

答えて

2

大規模な疎行列を扱う行列パッケージを基底Rよりも効率的に使用することを検討することもできます。どの行と列を1にするかを記述することで、0と1のスパース行列を構築できます。

library(Matrix) 
Test <- list(
    col1=list(2,4,7), 
    col2=list(3,2,6,8), 
    col3=list(1,4,5,3,7) 
) 
n.ids <- sapply(Test,length) 
vals <- unlist(Test) 
out <- sparseMatrix(vals, rep(seq_along(n.ids), n.ids)) 

可能であればあなたは人生はずっと楽になり、実行可能なコードの形で、いくつかのサンプルデータを与える場合、結果は

> out 
8 x 3 sparse Matrix of class "ngCMatrix" 

[1,] . . | 
[2,] | | . 
[3,] . | | 
[4,] | . | 
[5,] . . | 
[6,] . | . 
[7,] | . | 
[8,] . | . 
+0

まさに私が探していたものです。主な使い方は、 'n.ids < - ' sapply(Test、length) 'と ' rep(seq_along(n.ids)、n.ids) 'を使って行列にインデックスを作成することです。ありがとう! – Ron

+0

'rep(seq_along(n.ids)、n.ids)'は天才です。ありがとうございました。 – Zach

0

ここに、あなたの説明に合ったサンプルデータがあります。

a <- as.list(sample(20, 5)) 
b <- as.list(sample(20, 5)) 
c <- as.list(sample(20, 5)) 
abc <- list(a = a, b = b, c = c) 

私は、ネストされたlapply()でこれを行う方法が表示されていないが、ここでもう一つの方法です。 unlist()を削除するとよいでしょうが、他の誰かがこれを改善する可能性があります。

sp_to_bin <- function(splist) { 
    binlist <- numeric(100) 
    binlist[unlist(splist)] <- 1 
    return(binlist) 
} 
bindf <- data.frame(lapply(abc, sp_to_bin)) 
5

マトリックスを必要とする場合は、これを行うことはできません。

は、あなたがこのように構成リストがあるとしましょう:

Test <- list(
    col1=list(2,4,7), 
    col2=list(3,2,6,8), 
    col3=list(1,4,5,3,7) 
) 

まずあなたは正しい寸法のゼロで行列を構築します。あらかじめそれらを知っていれば、簡単です。そうしないとあなたが簡単に導き出すことができます。これは、与え

id <- unlist(Test)+rep(0:(n.cols-1),n.ids)*n.rows 
out[id] <- 1 
colnames(out) <- names(Test) 

> out 
    col1 col2 col3 
[1,] 0 0 1 
[2,] 1 1 0 
[3,] 0 1 1 
[4,] 1 0 1 
[5,] 0 0 1 
[6,] 0 1 0 
[7,] 1 0 1 
[8,] 0 1 0 

n.cols <- length(Test) 
n.ids <- sapply(Test,length) 
n.rows <- max(unlist(Test)) 
out <- matrix(0,nrow=n.rows,ncol=n.cols) 

を次に、行列が一つになる必要があり、各セルのインデックスを計算するために列方向に満たされているという事実を使用します

+1

+1これはかなり巧妙です.1-dインデックスベクトルを使って行列に割り当てる(または行列から抽出する)ことができます。また、事前に割り当てられた行列を埋め込むことは、他のアプローチよりもはるかに高速です。 ( '' do.call(cbind、lapply(...)) 'を使って)繰り返す '' cbind''操作を自然に思い浮かばせます。 –

2

Jorisの例を使用して、sapply/replaceを使用する構文的に簡単な方法を次に示します。私はJorisのアプローチが事前に割り当てられたマトリックスを埋めるのでより速いのですが、私のアプローチは暗黙的にcbindという列を含んでいるので、列のメモリ割り当てを繰り返す必要があります。

Test <- list( 
col1=list(2,4,7), 
col2=list(3,2,6,8), 
col3=list(1,4,5,3,7) 
) 

> z <- rep(0, max(unlist(Test))) 
> sapply(Test, function(x) replace(z,unlist(x),1)) 
    col1 col2 col3 
[1,] 0 0 1 
[2,] 1 1 0 
[3,] 0 1 1 
[4,] 1 0 1 
[5,] 0 0 1 
[6,] 0 1 0 
[7,] 1 0 1 
[8,] 0 1 0 
+0

コンピュータ上のタイミングは、ベクトルのリストを持っていれば速くなります。 (x)をunlist(x)に変更する必要があります。 –

+0

@Joris - 実際には 'unlist(x) ) 'まず、何らかの理由で私はそれを' c(x) 'に変更したときにうまくいったと思っていました...私はカット/ペーストで何かを乱したと思います。 w私は 'c(x)'でエラーを取得します。 –

0

あなたはまた、出力行列を埋めるために、行列インデックスベクトルを使用することができ、出力行列を埋めるために、スカラーインデックスベクトルを使用ヨリスの答え、上に構築します。後で書いたり理解したりするのが少しはっきりしていることがあります。

Test <- list(
    col1=list(2,4,7), 
    col2=list(3,2,6,8), 
    col3=list(1,4,5,3,7) 
) 

n.cols <- length(Test) 
n.ids <- sapply(Test,length) 
vals <- unlist(Test) 
n.rows <- max(vals) 
idx <- cbind(vals, rep(seq_along(n.ids), n.ids)) 
out <- matrix(0,nrow=n.rows,ncol=n.cols) 
out[idx] <- 1 
colnames(out) <- names(Test) 

結果は同じです。

関連する問題