【问题标题】:Sort column in R: strings first (alphabetically), then numbers (numerically)R中的列排序:首先是字符串(按字母顺序),然​​后是数字(按数字顺序)
【发布时间】:2022-01-01 21:51:47
【问题描述】:

我在 R 中有一个数据框,其中有一列由字母和数字组成(例如“A”、“B”、“1”、“2”等)。 我想以这样一种方式对数据框进行排序,即我首先有字母(按字母顺序排序),然后是数字(按数字排序)。理想情况下以一种整洁的方式,但不一定。

gtools::mixedsort 几乎可以满足我的要求,但将数字放在字符串之前,我认为没有一个参数可以让您将数字推到后面。

我考虑拆分数据框,分别对每个数据框进行排序,然后再次按行绑定。但我猜应该有更好的方法来做到这一点?

这也是进一步澄清我的问题的示例。

我有:

Col1    Col2   Col3
Apples     A     90
Pears     12     90
Bananas    C     50
Cake       1     50
Apples     A     90
Pears      B     90
Bananas    2     50
Cake     100     50

我试图实现的是按 Col2 排序,先按字母顺序,然后按数字:

Col1    Col2   Col3
Apples     A     90
Apples     A     90
Apples     A     90
Apples     A     90
Pears      B     90
Bananas    C     50
Cake       1     50
Bananas    2     50
Pears     12     90
Cake     100     50

非常感谢!

【问题讨论】:

    标签: r sorting


    【解决方案1】:

    对于基本 R 选项:

    df <- data.frame(Col2=c("100", "B", "A", "Z", "10", "4"), stringsAsFactors=FALSE)
    df[order(grepl("^\\d+$", df$Col2), sprintf("%10s", df$Col2)), ]
    
    [1] "A"   "B"   "Z"   "4"   "10"  "100"
    

    这里的两个排序级别首先将字母放在数字之前。第二个排序级别左将所有内容填充为 10 个字符,并用零填充。然后按升序排序。这实际上是数字的升序数字排序。这里的诀窍是要意识到,如果数字字符串都具有相同的宽度,那么它们实际上确实可以正确排序为文本。

    【讨论】:

      【解决方案2】:

      也许不是最佳解决方案,但使用 dplyr 并调用 df 您提供的数据:

      numbers <- df %>% 
        filter(!(Col2 %in% LETTERS)) %>% 
        mutate(Col2 = as.numeric(Col2)) %>% 
        arrange(Col2) %>% 
        mutate(Col2 = as.character(Col2))
      
      non_numbers <- df %>% 
        filter(Col2 %in% LETTERS) %>% 
        arrange(Col2)
      
      output <- rbind(non_numbers, numbers)
      

      输出:

          Col1 Col2 Col3
      1  Apples    A   90
      2  Apples    A   90
      3   Pears    B   90
      4 Bananas    C   50
      5    Cake    1   50
      6 Bananas    2   50
      7   Pears   12   90
      8    Cake  100   50
      

      【讨论】:

        【解决方案3】:

        不是按照您想要的确切顺序。但行绑定可以解决这个问题。

        DT <- fread("Col1    Col2   Col3
        Apples     A     90
        Pears     12     90
        Bananas    C     50
        Cake       1     50
        Apples     A     90
        Pears      B     90
        Bananas    2     50
        Cake     100     50")
        
        library(gtools)
        DT[mixedorder(DT$Col2),]
        

        【讨论】:

          【解决方案4】:

          您可以使用as.numeric 将数字转换为数字,使用is.na&lt;-order 这两个向量将数字的位置替换为NA

          s <- c(-1, -10, 2.5, "1e2", "A", 12, "C", 1, "A", "B", 2, 100)
          
          x <- suppressWarnings(as.numeric(s))
          s[order('is.na<-'(s, !is.na(x)), x)]
          # [1] "A"   "A"   "B"   "C"   "-10" "-1"  "1"   "2"   "2.5" "12"  "1e2" "100"
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-09-03
            • 1970-01-01
            • 2014-01-10
            • 2013-06-29
            • 2021-09-03
            • 2021-12-28
            相关资源
            最近更新 更多