web-dev-qa-db-ja.com

行列のベクトル化

1000 x 1000の大きな2Dマトリックスがあります。これを1列(または行)になるように変形したいと思います。たとえば、マトリックスが次の場合:

A B C
1 4 7
2 5 8
3 6 9

私はそれを有効にしたい:

1 2 3 4 5 6 7 8 9

列ヘッダーを保持する必要はなく、データの順序だけを保持する必要があります。 reshape2(これが最も使いやすいと推定したパッケージ)を使用してこれを行うにはどうすればよいですか?


明確にするために、reshapeに言及しました。これが最善の方法だと思いました。私は完全に満足している簡単な方法があることがわかります。

36
djq

よりコンパクトな方法を見つけるのは難しいと思います:

c(m)
[1] 1 2 3 4 5 6 7 8 9

ただし、マトリックス構造を保持する場合は、このdim属性の修正が効果的です。

dim(m) <- c(dim(m)[1]*dim(m)[2], 1)
m
      [,1]
 [1,]    1
 [2,]    2
 [3,]    3
 [4,]    4
 [5,]    5
 [6,]    6
 [7,]    7
 [8,]    8
 [9,]    9

次元の積を取得するよりコンパクトな方法がありますが、上記の方法は、dim属性が行列の2要素ベクトルであることを強調しています。その例で「9」を取得する他の方法は次のとおりです。

> prod(dim(m))
[1] 9
> length(m)
[1] 9
49
42-

可能な解決策ですが、reshape2を使用しません。

> m <- matrix(c(1:9), ncol = 3)
> m
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9
> as.vector(m)
[1] 1 2 3 4 5 6 7 8 9
13
EDi

Rの皆さん、OPにreshape2ソリューションを提供しましょう:

> m <- matrix(c(1:9), ncol = 3)
> melt(m)$value
[1] 1 2 3 4 5 6 7 8 9

私はそれがc(m)よりもどれだけ遅いかをテストするだけでは困りません。ただし、同じです:

> identical(c(m),melt(m)$value)
[1] TRUE

[編集:冗談だろ

> system.time(for(i in 1:1000){z=melt(m)$value})
   user  system elapsed 
  1.653   0.004   1.662 
> system.time(for(i in 1:1000){z=c(m)})
   user  system elapsed 
  0.004   0.000   0.004 
10
Spacedman

as.vector(m)はc(m)より少し効率的です:

> library(rbenchmark)
> m <- diag(5000)
> benchmark(
+   vect = as.vector(m), 
+   conc = c(m), 
+   replications=100
+ )
  test replications elapsed relative user.self sys.self user.child sys.child
2 conc          100  12.699    1.177     6.952    5.754          0         0
1 vect          100  10.785    1.000     4.858    5.933          0         0
3
df239

関数「sapply」を使用してそれを行うもう1つの簡単な方法(または、「for」ループでも同じことができます)

 m <- matrix(c(1:9), ncol = 3)
 (m1 <- as.numeric(sapply(1:NROW(m), function(i)(m[,i]))))
0
user36478