【问题标题】:Homogenize use of single and double digit numbers in string同质化使用字符串中的一位数和两位数
【发布时间】:2018-12-08 22:41:44
【问题描述】:

我有一个非常大的 data.table,其中(大量)项目由字符串定义,包括文本和数字。

library(data.table)    
dd <- data.table(x = c("A4","A4","A4","A14","A14","A14","B4","B4","B4"),y = c("A4","A14","B4","A4","A14","B4","A4","A14","B4"), z = c(1,2,3,4,5,6,7,8,9))

x   y   z
A4  A4  1
A4  A14 2
A4  B4  3
A14 A4  4
A14 A14 5
A14 B4  6
B4  A4  7
B4  A14 8
B4  B4  9

数字可以是一位数或两位数,因此 R 将始终根据数字中的第一个数字(A14 在 A4 之前)对它们进行排序。混合排序可以处理这个问题。但是,当我将长数据重塑为宽时

wide <- dcast(dd, x ~ y, value.var = "z")

R 正在根据基本排序规则再次应用排序。

x    A14  A4  B4
A14  5    4   6
A4   2    1   3
B4   8    7   9

但是,我需要以下矩阵计算的原始顺序。有没有任何有效的方法可以将字符串 + 个位数重命名为字符串 + 双位数(A4 -> A04)或我错过的另一种方法?

【问题讨论】:

    标签: r string data.table data-management


    【解决方案1】:

    您可以使用sprintf() 在数字前加0

    sprintf("%s%02.0d", "A",  1:20)
    # [1] "A01" "A02" "A03" "A04" "A05" "A06" "A07" "A08" "A09" "A10" "A11" "A12" "A13" "A14" "A15" "A16" "A17" "A18" "A19" "A20"
    

    【讨论】:

    • 我相信使用"%s%02d"这样的整数格式会更好。无论如何都要点赞。
    【解决方案2】:

    您可以将0s 添加到您的数据中

    dd[nchar(x) == 2, x := paste0(substr(x, 1, 1), 0, substr(x, 2, 2))]
    dd[nchar(y) == 2, y := paste0(substr(y, 1, 1), 0, substr(y, 2, 2))]
    
    #      x   y z
    # 1: A04 A04 1
    # 2: A04 A14 2
    # 3: A04 B04 3
    # 4: A14 A04 4
    # 5: A14 A14 5
    # 6: A14 B04 6
    # 7: B04 A04 7
    # 8: B04 A14 8
    # 9: B04 B04 9
    

    或者,如果您需要申请更多列:

    to.change <- c('x', 'y')
    
    dd[, (to.change) := lapply(.SD, function(x) ifelse(nchar(x) > 2, x
                                                       , paste0(substr(x, 1, 1), 0, substr(x, 2, 2))))
       , .SDcols = to.change]
    

    【讨论】:

      【解决方案3】:

      此解决方案中不需要额外的零。

      # Data frame
      df <- data.frame(x = c("A4","A4","A4","A14","A14","A14","B4","B4","B4"),
                       y = c("A4","A14","B4","A4","A14","B4","A4","A14","B4"), 
                       z = c(1,2,3,4,5,6,7,8,9),
                       stringsAsFactors = FALSE)
      
      # Reorder columns and rows using `mixedsort`. 
      wide <- dcast(df, x ~ y,value.var   = "z") %>% 
        select(x, mixedsort(unique(df$x))) %>% 
        slice(match(x, mixedsort(unique(df$x))))
      

      给予,

      #     x A4 A14 B4
      # 1  A4  1   2  3
      # 2 A14  4   5  6
      # 3  B4  7   8  9
      

      【讨论】:

        【解决方案4】:

        另一个可能也是最简单的选项是使用来自gtools-package 的mixedorder:

        wide <- dcast(dd, x ~ y, value.var = "z")[gtools::mixedorder(x)]
        

        给出:

        > wide
             x A14 A4 B4
        1:  A4   2  1  3
        2: A14   5  4  6
        3:  B4   8  7  9
        

        如果你也想用同样的方式设置列顺序,你可以另外使用setcolorder:

        setcolorder(wide, c(1, gtools::mixedorder(names(wide)[-1]) + 1))
        

        然后给出:

        > wide
             x A4 A14 B4
        1:  A4  1   2  3
        2: A14  4   5  6
        3:  B4  7   8  9
        

        【讨论】:

          【解决方案5】:

          您可能需要考虑通过因子直接在数据中实现此顺序,因此您不必稍后通过数据整理来修复它。

          如果您已经将这些唯一值排序在某个地方,则不需要mixedorder 而不是mixedsort,那么只需将它们转换为因子。

          否则你可以取回订单:

          library(gtools)
          dd[,1:2] <- lapply(dd[,1:2],function(x) factor(x, mixedsort(unique(x))))
          

          然后正常进行:

          dcast(dd, x ~ y, value.var = "z")
          #      x A4 A14 B4
          # 1:  A4  1   2  3
          # 2: A14  4   5  6
          # 3:  B4  7   8  9
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-09-09
            • 1970-01-01
            • 2013-09-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-08-24
            相关资源
            最近更新 更多