【问题标题】:How to order my dataframe lexicographicaly如何按字典顺序订购我的数据框
【发布时间】:2019-08-01 17:30:11
【问题描述】:

我有以下数据框

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 的整个数据框进行排序?
  • 我想针对 c 对整个数据框进行排序。为了便于理解,我给了一个[,"c"]

标签: r sorting r-faq


【解决方案1】:

一种选择是使用 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

【讨论】:

  • 如何同时使用多列进行排序(先是 c,然后是 b,然后是 a)?
  • @user1631306 在 plyr 包中尝试arrange
  • @user1631306 -- 在这种情况下,您可以这样做:a[with(a, order(mixedorder(c), b, a)),]
【解决方案2】:

坚持基础你可以自己做一个功能:

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))

【讨论】:

    【解决方案3】:

    不幸的是,混合排序(还)不支持多列排序。所以,你需要自己实现它,例如这样:

    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 对 data.frame 进行字母数字排序,对于平局情况(实际上在您的 data.frame '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 在this post 中对类似问题的回复。

    【讨论】:

      【解决方案4】:

      假设这些是人类染色体名称,chr1...chr22, chrX, chrY。我们可以将它们转换为数字,然后使用 order:

      # 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-06-10
        • 2011-05-15
        • 2014-02-14
        • 1970-01-01
        • 1970-01-01
        • 2011-11-07
        • 1970-01-01
        相关资源
        最近更新 更多