【问题标题】:R: order a vector of strings with both character and numeric values both alphabetically and numericallyR:按字母和数字顺序对具有字符和数值的字符串向量进行排序
【发布时间】:2014-02-02 03:26:52
【问题描述】:

我有一个包含字符和数值的字符串向量。例如:

a=c("ILLUMINA:420:C2D7UACXX:1:1102:14591:91480","ILLUMINA:420:C2D7UACXX:1:1102:14592:3881","ILLUMINA:420:C2D7UACXX:1:1102:14592:37103","ILLUMINA:420:C2D7UACXX:1:1102:14592:37356")

我想对向量进行排序,以便字符按字母顺序排序,数字按数字排序。字符串的结构始终采用以下格式: "ILLUMINA:420:C2D7UACXX:1:<number>:<number>:<number>",所以实际上这个顺序只适用于最后三个冒号分隔的数字。

我确实尝试过mixedsort {gtools},但结果与使用sort 和

sort.int,即:

> mixedsort(a)
[1] "ILLUMINA:420:C2D7UACXX:1:1102:14591:91480" "ILLUMINA:420:C2D7UACXX:1:1102:14592:37103"
[3] "ILLUMINA:420:C2D7UACXX:1:1102:14592:37356" "ILLUMINA:420:C2D7UACXX:1:1102:14592:3881"

显然正确的顺序应该是:

[1] "ILLUMINA:420:C2D7UACXX:1:1102:14591:91480" "ILLUMINA:420:C2D7UACXX:1:1102:14592:3881" 
[3] "ILLUMINA:420:C2D7UACXX:1:1102:14592:37103" "ILLUMINA:420:C2D7UACXX:1:1102:14592:37356"

有什么立竿见影的解决办法吗?

【问题讨论】:

    标签: r sorting vector


    【解决方案1】:

    gtools::mixedsort 确实适用于您的情况,实际上:

    > a=c("ILLUMINA:420:C2D7UACXX:1:1102:14591:91480",
          "ILLUMINA:420:C2D7UACXX:1:1102:14592:3881",
          "ILLUMINA:420:C2D7UACXX:1:1102:14592:37103",
          "ILLUMINA:420:C2D7UACXX:1:1102:14592:37356")
    > 
    > mixedsort(a)
    [1] "ILLUMINA:420:C2D7UACXX:1:1102:14591:91480"
    [2] "ILLUMINA:420:C2D7UACXX:1:1102:14592:3881" 
    [3] "ILLUMINA:420:C2D7UACXX:1:1102:14592:37103"
    [4] "ILLUMINA:420:C2D7UACXX:1:1102:14592:37356"
    

    我正在使用 gtools_3.4.2 和 R-3.2.0

    【讨论】:

      【解决方案2】:

      这里有一个更快的解决方案:

      fields.list = strsplit(a,split=":")
      sort.dt = data.table(t(sapply(fields.list,function(x) as.numeric(c(x[5],x[6],x[7])))))
      sorted.a = v[with(sort.dt,order(V1,V2,V3))]
      > sorted.a
      [1] "ILLUMINA:420:C2D7UACXX:1:1102:14591:91480" "ILLUMINA:420:C2D7UACXX:1:1102:14592:3881"  "ILLUMINA:420:C2D7UACXX:1:1102:14592:37103"
      [4] "ILLUMINA:420:C2D7UACXX:1:1102:14592:37356"
      

      【讨论】:

        【解决方案3】:

        EDIT在OP澄清后彻底改变解决方案

        您可以提取最后 3 个元素和顺序,然后创建一个 data.frame:

        dat = read.table(text=sub('.*:1:([0-9]+):([0-9]+):([0-9]+)','\\1|\\2|\\3',a),sep='|')
         dat
            V1    V2    V3
        1 1102 14591 91480
        2 1102 14592  3881
        3 1102 14592 37103
        4 1102 14592 37356
        

        然后您使用 3 列订购:

         a[with(dat,order(V1,V2,V3))]
        [1] "ILLUMINA:420:C2D7UACXX:1:1102:14591:91480" "ILLUMINA:420:C2D7UACXX:1:1102:14592:3881" 
        [3] "ILLUMINA:420:C2D7UACXX:1:1102:14592:37103" "ILLUMINA:420:C2D7UACXX:1:1102:14592:37356"
        

        【讨论】:

        • 非常接近。如果我将您的解决方案稍微编辑为: a[order(sub('.*:1:([0-9]+):([0-9]+):([0-9]+)',as. numeric('\\1\\2\\3'),a))] 我得到:[1] "ILLUMINA:420:C2D7UACXX:1:1102:14591:91480" "ILLUMINA:420:C2D7UACXX:1: 1102:14592:3881" [3] "ILLUMINA:420:C2D7UACXX:1:1102:14592:37103" "ILLUMINA:420:C2D7UACXX:1:1102:14592:37356" 但带有此警告:警告消息:在 sub( ".*:1:([0-9]+):([0-9]+):([0-9]+)", as.numeric("\\1\\2\\3") , : 强制引入的 NA 我应该关心这个警告吗?
        • 谢谢!您认为这可以更有效地完成吗,因为我的字符串向量的长度约为一百万?
        • 就我而言,最后一个 ] 之前缺少一个逗号。结果:a[with(dat,order(V1,V2,V3)),]
        猜你喜欢
        • 2021-12-19
        • 1970-01-01
        • 2021-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-02
        • 2016-04-13
        • 1970-01-01
        相关资源
        最近更新 更多