2011-08-03 3 views
23

これはおそらく簡単に解決できます。私は、500行×335列のmatの2次元行列と、120425行のdata.frame datを持っています。 data.frame datには、IJという2つの列があり、これらの列は、行をインデックス化するための列であり、列はmatです。 matの値をdatの行に追加したいと思います。行を使用した行列からの索引値、コロン記号

は、ここに私の概念は失敗です:

> dat$matval <- mat[dat$I, dat$J] 
Error: cannot allocate vector of length 1617278737 

(私はWin32でR 2.13.1を使用しています)。ちょっと深く掘り下げると、サブマトリクスがmatになっているように見えますが、予想通りマトリックスの値が1次元ではないように見えます。

> str(mat[dat$I[1:100], dat$J[1:100]]) 
int [1:100, 1:100] 20 1 1 1 20 1 1 1 1 1 ... 

私はint [1:100] 20 1 1 1 20 1 1 1 1 1 ...のようなものを期待していました。値を取得するために行、列のインデックスを使用して2D行列をインデックスする正しい方法は何ですか? DWINが示唆するようにインデックス行列を用い

+0

+1(これは別の質問をします:N次元の '[' '演算子Nベクトルを渡すときに何かに動作を変更するオプションがないのはなぜですか?マトリックス?) –

+0

良い質問 - 私は*私が思う*を修正するためにそれを少し編集しました*はタイプミスです( 'datI'から' dat $ I')。これがあなたが元に戻すことを自由に感じていたのではない場合... – joran

答えて

37

を使用してワンライナーです。 、これはまた、データフレームのために働くが、それらは第1のマトリックスクラスに強制し、いずれかが非数値である場合にされています

dat$matval <- mat[ cbind(dat$I, dat$J) ] # should do it. 

注意点があります:2列の行列として「[」に提供する必要があります行列全体が「最低分母」クラスになります。

+1

Rが明らかに物事を行うことを意図した方法を見つけるために+1 –

+0

'I'と' J'だけが唯一の 'マット[dat] '十分な?あるいは、マトリックスに強制する必要がありますか? – joran

+1

データフレームが本当にリストなので強制変換が必要です。だから、あなたは 'as.matrix(dat)'を実行することもできます。 – joran

10

は、もちろん非常にクリーンであるが、手動で1-Dのインデックスを使用してそれを行ういくつかの奇妙な理由のためにわずかに速い実際には:

# Huge sample data 
mat <- matrix(sin(1:1e7), ncol=1000) 
dat <- data.frame(I=sample.int(nrow(mat), 1e7, rep=T), 
        J=sample.int(ncol(mat), 1e7, rep=T)) 

system.time(x <- mat[cbind(dat$I, dat$J)])  # 0.51 seconds 
system.time(mat[dat$I + (dat$J-1L)*nrow(mat)]) # 0.44 seconds 

dat$I + (dat$J-1L)*nrow(m)部分は、2-オンD指数を1次元のものに変換する。 1Lは、double値の代わりに整数を指定する方法です。これにより、いくつかの強制が回避されます。

... gsk3の適用ベースのソリューションも試しました。これは、しかし、ほぼ500倍も遅いです:

system.time(apply(dat, 1, function(x,mat) mat[ x[1], x[2] ], mat=mat)) # 212 
1

はここでほとんどapplyの行ベースの操作

> dat <- as.data.frame(matrix(rep(seq(4),4),ncol=2)) 
> colnames(dat) <- c('I','J') 
> dat 
    I J 
1 1 1 
2 2 2 
3 3 3 
4 4 4 
5 1 1 
6 2 2 
7 3 3 
8 4 4 
> mat <- matrix(seq(16),ncol=4) 
> mat 
    [,1] [,2] [,3] [,4] 
[1,] 1 5 9 13 
[2,] 2 6 10 14 
[3,] 3 7 11 15 
[4,] 4 8 12 16 

> dat$K <- apply(dat, 1, function(x,mat) mat[ x[1], x[2] ], mat=mat) 
> dat 
    I J K 
1 1 1 1 
2 2 2 6 
3 3 3 11 
4 4 4 16 
5 1 1 1 
6 2 2 6 
7 3 3 11 
8 4 4 16 
0
n <- 10 
mat <- cor(matrix(rnorm(n*n),n,n)) 
ix <- matrix(NA,n*(n-1)/2,2) 
k<-0 
for (i in 1:(n-1)){ 
    for (j in (i+1):n){ 
    k <- k+1 
    ix[k,1]<-i 
    ix[k,2]<-j 
    } 
} 
o <- rep(NA,nrow(ix)) 
o <- mat[ix] 
out <- cbind(ix,o) 
+2

いくつかのコメントは素敵で、答えをより「魅力的」にする。 –

+1

あなたは一束のコードにしか答えることができません...さあ...あなたの答えを少し説明してください:) –

関連する問題