将矩阵向量化

36

我有一个大的2D矩阵,大小为1000 x 1000。我想将其重塑为一列(或一行)。例如,如果矩阵是:

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

我想把它变成:

1 2 3 4 5 6 7 8 9

我不需要保留列标题,只需保留数据的顺序。如何使用reshape2(我认为这是最容易使用的包)完成此操作?


仅作澄清,我提到reshape是因为我认为这是最好的方法。 我可以看到有更简单的方法,这对我来说完全可以接受。


7
当你将矩阵进行向量化时,请记住它总是按列进行。当你需要保留行顺序时,可以使用 c(t(some.matrix)) - Joris Meys
1
更改标题以反映所提出的问题。顺便问一句,我想知道那种重塑狂热是从哪里来的。我看到很多问题都要求用重塑来解决问题,而这些问题本来就不是重塑最初设计的解决方案。 - Joris Meys
4
也许你想要表达的是:如果你手中只有一把锤子,那么所有东西看起来都像钉子? - Joshua Ulrich
@Joris - 真的是无知。我只是假设我想做的不是标准操作。我使用ggplot2,有时会提到reshape2,因为它们都是由Hadley Wickham制作的。 - djq
5个回答

54

我认为很难找到比下面更简洁的方法:

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属性是矩阵的两个元素向量。在该示例中获取“9”的其他方法包括:

> prod(dim(m))
[1] 9
> length(m)
[1] 9

6
您可以使用cbind(c(m))将其转换为单列矩阵。 - Prasad Chalasani
2
@hadley 好的,prod(dim(m))怎么样? - IRTFM
1
dim(m) <- c(prod(dim(m)), 1) 这个写法更好一些,而且适用于任意维度。 - hadley
这就是我想让读者做的事情。代码 prod(dim(m)) 被提供作为笨重的 dim(m)[1]*dim(m)[2] 的替代方式,以达到得到 9 的目的。它一直被设计用于进入 dim(m)<-c(prod(dim(m)), 1),我猜这就是为什么我无法理解你的评论的原因。 - IRTFM
对于任何拥有 data.frame 的人,unlist(df) 都可以使用。 - kdauria

13
一种可能的解决方案,但不使用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

3
as.vector(m) 的速度大约是 c(m) 的一半 - 尽管在这里时间很可能并不那么重要。 - Spacedman

11

来吧,R语言的人,让我们给提问者提供一个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 

重塑解决方案在测试1000 x 1000矩阵时速度慢了几个数量级...正如您可以通过编辑看到的那样。;-) - Joshua Ulrich
+1 对于时间的准确度。有趣的重塑技巧,虽然我不会想到它。出于显而易见的原因;-) - Joris Meys
只是为了娱乐:reshape2::melt 比 reshape::melt 快大约25%(10000次重复的时间分别为7.7秒和10.3秒),但仍然比c(m)慢约400倍... - Ben Bolker

4

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

0

使用函数"sapply"是另一种简单的方法(也可以使用'for'循环完成相同的操作)

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接