刚才在R-help的maillist里看到有人求助matrix的排序问题,已知如下一组数据:

text
12 0.5
21 0.3
31 0.5
43 0.2

希望能够按第一列升序、第二列降序的方式排列,得出:

text
11 0.5
21 0.3
32 0.5
43 0.2

在R的帮助中找了找,竟然只有一维向量的排序,对于多维向量(矩阵或数据框)也顶多只能根据其中一行或一列排序。不知道是我眼拙,还是我接触的库太少,总之没什么收获。很快该问题有人回答,给出了如下解决方法:

r
 1> x <- matrix( c(2, 1, 1, 3, .5, .3, .5, .2), 4)
 2> x
 3[,1] [,2]
 4[1,] 2 0.5
 5[2,] 1 0.3
 6[3,] 1 0.5
 7[4,] 3 0.2
 8> cbind(sort(x[,1]), unlist(tapply(x[,2], x[,1], sort, decreasing = T)))
 9[,1] [,2]
1011 1 0.5
1112 1 0.3
122 2 0.5
133 3 0.2

然而,个人感觉这种方式不是太爽,于是琢磨半天,使用了递归,写了如下函数:

r
 1order.matrix <- function(m, columnsDecreasing = c('1'=FALSE), rows = 1:nrow(m))
 2{
 3    if (length(columnsDecreasing) > 0)
 4    {
 5        col <- as.integer(names(columnsDecreasing[1]));
 6        values <- sort(unique(m[rows, col]), decreasing=columnsDecreasing[1]);
 7        unlist(sapply(values, function(x)
 8                    order.matrix(m, columnsDecreasing[-1], which((1:nrow(m) %in% rows) & (m[,col]==x)))));
 9    }
10    else
11    {
12        rows;
13    }
14}

运行结果:

r
 1> m <- matrix( c(2, 1, 1, 3, .5, .3, .5, .2), 4)
 2> m
 3[,1] [,2]
 4[1,] 2 0.5
 5[2,] 1 0.3
 6[3,] 1 0.5
 7[4,] 3 0.2
 8> m[order.matrix(m),]
 9[,1] [,2]
10[1,] 1 0.3
11[2,] 1 0.5
12[3,] 2 0.5
13[4,] 3 0.2
14> m[order.matrix(m, c("1"=FALSE, "2"=TRUE)),]
15[,1] [,2]
16[1,] 1 0.5
17[2,] 1 0.3
18[3,] 2 0.5
19[4,] 3 0.2

貌似解决了根据任意多列排序的一般性问题,效果还不错,自己先得意了一下。

但很快有人给出了更简单直接的解决方法:

r
1> m[order(m[,1],-m[,2]),]
2[,1] [,2]
3[1,] 1 0.5
4[2,] 1 0.3
5[3,] 2 0.5
6[4,] 3 0.2

看来还是对R不够了解啊!