4

如何在每列的唯一值总数上列一个列reorderdata.frame举个例子:

var1 var2 var3
  1    1   1
  0    2   2
  1    3   3
  0    4   1
  1    5   2

有没有办法像这样var2, var3, var1自动重新排序(因为唯一值的长度分别是 5、3 和 2,或者相反,2 3 5)?

在这种情况下,得到我们想要的东西并不难,但在我的情况下,我有很多专栏。有没有办法自动进行这种类型的排序?

此外,我更希望有一个适用于matrix(除了data.frame)的解决方案,与是否有列名无关。

4

2 回答 2

7

像这样的东西?

df[names(sort(sapply(df, function(x) length(unique(x))), decreasing = TRUE))]

#   var2 var3 var1
# 1    1    1    1
# 2    2    2    0
# 3    3    3    1
# 4    4    1    0
# 5    5    2    1

如果您的输入是 a matrix,则:

m[, names(sort(apply(m, 2, function(x) 
       length(unique(x))), decreasing = TRUE))] 

应该管用。

#      var2 var3 var1
# [1,]    1    1    1
# [2,]    2    2    0
# [3,]    3    3    1
# [4,]    4    1    0
# [5,]    5    2    1

编辑:您在帖子中的示例似乎有列名,但您在评论中给出的这个没有。请确保正确生成示例。

X <- cbind(1, rnorm(10), 1:10)

由于您不能期望列名,因此您必须返回索引。试试这个(当然,如果你有列名,它会起作用):

m[, sort(apply(X, 2, function(x) 
         length(unique(x))), decreasing = TRUE, index.return = TRUE)$ix]
于 2013-03-06T11:07:20.637 回答
5

另一种使用的解决方案order

dat[,order(apply(dat,2,function(x) length(unique(x))),decreasing = TRUE)]
  var2 var3 var1
1    1    1    1
2    2    2    0
3    3    3    1
4    4    1    0
5    5    2    1

现在,如果我们把删除列名,我们仍然会得到好的结果,但有一个警告

 colnames(dat) <- NULL
 dat[,order(apply(dat,2,function(x) length(unique(x))),decreasing = TRUE)]
  NA NA NA
1  1  1  1
2  2  2  0
3  3  3  1
4  4  1  0
5  5  2  1

编辑测试性能:

我在一个有 1000 列的矩阵上进行测试。2 个解的时间是可比的,略有增益order

X <- matrix(rnorm(100*1000),ncol=1000,nrow=100)
Arun <- function() X[, sort(apply(X, 2, function(x) 
  length(unique(x))), decreasing = TRUE, index.return = TRUE)$ix]

AgStudy <- function()  X[,order(apply(X,2,function(x) length(unique(x))),decreasing = TRUE)]

library(microbenchmark)

microbenchmark(Arun(),AgStudy())

Unit: milliseconds
       expr      min       lq   median       uq      max
1 AgStudy() 28.04634 32.37105 34.73820 36.49930 129.6048
2    Arun() 31.15476 32.97180 36.24027 37.91584 132.3871
于 2013-03-06T11:33:13.443 回答