如何按字典序对我的数据框进行排序

9

I have a following data frame

a = data.frame(a=c(1,2,3,4,5,6,7),b=c(1,2,3,10,12,21,4),c=c(1,2,10,11,"X","Y",3))
> a
  a  b  c
1 1  1  1
2 2  2  2
3 3  3 10
4 4 10 11
5 5 12  X
6 6 21  Y
7 7  4  3

我希望对整个数据框进行词典序排序,以便输出结果(例如,“c”列)如下:
> a[,"c"]
[1] 1  2  3 10 11  X  Y

我尝试了,但得到了不同的答案。

indata <- a[do.call(order,a[,c("c","a","b")]),]
> indata[,"c"]
[1] 1  10 11 2  3  X  Y
Levels: 1 10 11 2 3 X Y

我尝试了gtools和mixedorder包,在一个列上表现良好:

> a[mixedorder(a$c),]
  a  b  c
1 1  1  1
2 2  2  2
3 3  3 10
4 4 10 11
5 5 12  X
6 6 21  Y
7 7  4  3

但是如果我包含多列,它就无法正常工作:

> a[with(a,order(mixedorder(c),mixedorder(b),mixedorder(a))),]
  a  b  c
1 1  1  1
2 2  2  2
4 4 10 11
5 5 12  X
6 6 21  Y
7 7  4  3
3 3  3 10

尽管我期望着:
  a  b  c
1 1  1  1
2 2  2  2
4 7  4  3
5 3  3 10
6 4 10 11
7 5 12  X
3 6 21  Y

你需要更清楚一些。你是想只对列 c 进行排序,还是想根据列 c 对整个数据框进行排序? - joran
我想根据c对整个数据框进行排序。为了方便理解,我使用了a [,“c”]。 - user1631306
1
相关帖子:https://stackoverflow.com/q/19014531/680068 - zx8754
4个回答

7

一个选项是使用gtools包中的mixedorder()函数。

library(gtools)
a[mixedorder(a$c),]
#   a  b  c
# 1 1  1  1
# 2 2  2  2
# 7 7  4  3
# 3 3  3 10
# 4 4 10 11
# 5 5 12  X
# 6 6 21  Y

1
如何同时使用多列进行排序(先按c排,然后按b排,最后按a排)? - user1631306
1
尝试使用 plyr 包中的 arrange - joran
2
@user1631306 -- 在这种情况下,您可以这样做:a[with(a, order(mixedorder(c), b, a)),] - Josh O'Brien

4

你可以在基础中自己创建一个函数:

a = data.frame(a=c(1,2,3,4,5,6,7),b=c(1,2,3,10,12,21,4),c=c(1,2,10,11,"X","Y",3))

SORTER_DEVICE <- function(x) {
    c(sort(as.numeric(na.omit(gsub("[a-zA-Z]", NA, x)))),
        sort(na.omit(gsub("[0-9]", NA, x))))
}
data.frame(apply(a, 2, SORTER_DEVICE))

1

很遗憾,mixedsort目前不支持多列排序。因此,您需要自己实现它,例如像这样:

a[order(sub("[0-9]+", "", a$c),
        as.numeric(sub("[[:alpha:]]*([[:digit:]]*)", '\\1', a$c)),
        as.numeric(a$b),
        as.numeric(a$a)), ]

首先,按照a$c对数据框进行字母数字排序,在出现并列的情况下(在您的数据框'a'中实际上不存在),使用a$b和a$a。

输出结果为:

  a  b  c
1 1  1  1
2 2  2  2
7 7  4  3
3 3  3 10
4 4 10 11
5 5 12  X
6 6 21  Y

PS:这篇文章是David Winsemius在此帖子中作为对类似问题的回复所写。


1
假设这些是人类染色体的名称,chr1...chr22, chrX, chrY。我们可以将它们转换为数字,然后使用顺序:
# convert to numeric
a$chromN <- as.integer(ifelse(a$c == "X", "23", ifelse(a$c == "Y", "24", a$c)))

# now sort as usual:
a[ order(a$chromN), ]

#   a  b  c chromN
# 1 1  1  1      1
# 3 3  3 10      2
# 4 4 10 11      3
# 2 2  2  2      4
# 7 7  4  3      5
# 5 5 12  X     23
# 6 6 21  Y     24

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