R:对多个向量(列)进行混合排序

时间:2019-01-08 10:09:00

标签: r sorting dataframe natural-sort

这是标记为this questiona duplicate to this的后续行动,但是建议的解决方案不起作用。

我有以下data.frame

set.seed(1)
mydf <- data.frame(A=paste(sample(LETTERS, 4), sample(1:20, 20), sep=""),
        B=paste(sample(1:20, 20), sample(LETTERS, 4), sep=""),
        C=sample(LETTERS, 20), D=sample(1:100, 20), value=rnorm(20))

> mydf
     A   B C  D       value
1   G5  6N T  9 -0.68875569
2  J18  8T R 87 -0.70749516
3  N19  1A L 34  0.36458196
4  U12  7K Z 82  0.76853292
5  G11 14N J 98 -0.11234621
6   J1 20T F 32  0.88110773
7   N3 17A B 45  0.39810588
8  U14 19K W 83 -0.61202639
9   G9 15N U 80  0.34111969
10 J20  3T I 36 -1.12936310
11  N8  9A K 70  1.43302370
12 U16 16K G 86  1.98039990
13  G6 10N M 39 -0.36722148
14  J7 18T D 62 -1.04413463
15 N13  5A Y 35  0.56971963
16  U4 11K N 28 -0.13505460
17 G17  4N O 64  2.40161776
18 J15  2T C 17 -0.03924000
19  N2 12A P 59  0.68973936
20 U10 13K X 10  0.02800216

我想根据列AD对其进行排序,但是AD混合使用,因此需要自然顺序

我知道我可以应用常规订购,例如:

mydf2 <- mydf[do.call(order, c(mydf[1:4], list(decreasing = FALSE))),]

> mydf2
     A   B C  D       value
5  G11 14N J 98 -0.11234621
17 G17  4N O 64  2.40161776
1   G5  6N T  9 -0.68875569
13  G6 10N M 39 -0.36722148
9   G9 15N U 80  0.34111969
6   J1 20T F 32  0.88110773
18 J15  2T C 17 -0.03924000
2  J18  8T R 87 -0.70749516
10 J20  3T I 36 -1.12936310
14  J7 18T D 62 -1.04413463
15 N13  5A Y 35  0.56971963
3  N19  1A L 34  0.36458196
19  N2 12A P 59  0.68973936
7   N3 17A B 45  0.39810588
11  N8  9A K 70  1.43302370
20 U10 13K X 10  0.02800216
4  U12  7K Z 82  0.76853292
8  U14 19K W 83 -0.61202639
12 U16 16K G 86  1.98039990
16  U4 11K N 28 -0.13505460

但这不是我需要的结果。我需要10之后的9,而不是1之后的{(您可以检查列A来查看它是否与我需要的顺序不符。)

在我最初的问题的评论中,建议使用multi.mixedorder函数。

但是,如下所示,结果与仅使用order的结果相同,但这仍然不是我想要的。

multi.mixedorder <- function(..., na.last = TRUE, decreasing = FALSE){
    do.call(order, c(
        lapply(list(...), function(l){
            if(is.character(l)){
                factor(l, levels=mixedsort(unique(l)))
            } else {
                l
            }
        }),
        list(na.last = na.last, decreasing = decreasing)
    ))
}

mydf3 <- mydf[do.call(multi.mixedorder, c(mydf[1:4], list(decreasing = FALSE))),]

> mydf3
    A   B C  D       value
5  G11 14N J 98 -0.11234621
17 G17  4N O 64  2.40161776
1   G5  6N T  9 -0.68875569
13  G6 10N M 39 -0.36722148
9   G9 15N U 80  0.34111969
6   J1 20T F 32  0.88110773
18 J15  2T C 17 -0.03924000
2  J18  8T R 87 -0.70749516
10 J20  3T I 36 -1.12936310
14  J7 18T D 62 -1.04413463
15 N13  5A Y 35  0.56971963
3  N19  1A L 34  0.36458196
19  N2 12A P 59  0.68973936
7   N3 17A B 45  0.39810588
11  N8  9A K 70  1.43302370
20 U10 13K X 10  0.02800216
4  U12  7K Z 82  0.76853292
8  U14 19K W 83 -0.61202639
12 U16 16K G 86  1.98039990
16  U4 11K N 28 -0.13505460

1 个答案:

答案 0 :(得分:1)

好的,解决了,multi.mixedsort函数需要修复才能处理各种因素:

multi.mixedorder <- function(..., na.last = TRUE, decreasing = FALSE){
    do.call(order, c(
        lapply(list(...), function(l){
            if(is.character(l)){
                factor(l, levels=mixedsort(unique(l)))
            } else {
                factor(as.character(l), levels=mixedsort(levels(l)))
            }
        }),
        list(na.last = na.last, decreasing = decreasing)
    ))
}

否则,将mydf中的所有因子列转换为字符,并使用:

mydf[] <- lapply(mydf, as.character)

但已修复,因此不需要