R字符串操作:如何优化此字符串?

时间:2018-06-28 13:54:23

标签: r printf

TL; DR:我想通过左侧的给定字符将列表中的每个字符串完成为给定大小。我要它快。请参见下面的代码并举例

我有veeeeery的大字符串矢量,其中包含...以及任何东西,但最多(已知)个字符。我想通过将零保留为给定的大小(优于char的最大数量)来完成thoose字符串

假设:

c("yop",NA,"1234567","19","12AN","PLOP","5689777")

举例来说,我希望目标尺寸为10

[1] "0000000yop" NA "0001234567" "0000000019" "00000012AN" "000000PLOP" "0005689777"
结果,

尽可能快。

我试图写自己的书,但是速度不是很快。您能帮我更快吗?我有数十亿的苏糖可以治疗。

这是我的实际代码:

library(purrr)
zero_left <- function(field,nb){
  map2_chr(
    map(abs(nb-nchar(field)),~ rep("0",.x)),
    field,
    ~ paste0(c(.x,.y),collapse=""))
}

trial <- c("yop","1234567","19","12AN","PLOP","5689777")
zero_left(trial,10)

此代码甚至不处理NA情况...但是如果没有,它会起作用,但速度太慢。

2 个答案:

答案 0 :(得分:5)

这依赖于一个外部程序包,但是它需要您zero_left()函数花费的时间的1/30:

reduce

编辑1:

似乎是

Base-R解决方案可能不是只是这么快:

nb <- 10
stringr::str_pad(trial, width=nb, pad="0")
[1] "0000000yop" "0001234567" "0000000019" "00000012AN" "000000PLOP" "0005689777"

编辑2:

请记住,gsub(pattern = " ", replacement = "0", sprintf("%*s", nb, trial), fixed = TRUE) 只是stringr函数的包装器,您可以通过直接使用stringi获得另一个速度提升:

stringi

答案 1 :(得分:2)

如果您关心速度,则基R 可以比stringr / stringi快:

library(microbenchmark)
microbenchmark(
  stringr=stringr::str_pad(trial, width=nb, pad="0"),
  stringi=stringi::stri_pad_left(trial, width = nb, pad = "0"),
  base=paste(strrep("0", nb - nchar(trial)), trial, sep="")
)
# Unit: microseconds
#     expr    min     lq     mean  median      uq     max neval
#  stringr 21.292 22.747 24.87188 23.7070 24.4735 129.470   100
#  stringi 10.473 12.359 13.15298 13.0180 13.5445  21.418   100
#     base  7.848  9.392 10.83702 10.2035 10.8980  43.620   100

唯一的结果是NA在这里变成了文字"NANA"

paste(strrep("0", nb - nchar(trial)), trial, sep="")
# [1] "0000000yop" "NANA"       "0001234567" "0000000019" "00000012AN"
# [6] "000000PLOP" "0005689777"

所以解决方法是

microbenchmark(
      stringr=stringr::str_pad(trial, width=nb, pad="0"),
      stringi=stringi::stri_pad_left(trial, width = nb, pad = "0"),
      base={v=paste(strrep("0", nb - nchar(trial)), trial, sep="");v[is.na(trial)]=NA;}
    )
# Unit: microseconds
#     expr    min      lq     mean  median      uq    max neval
#  stringr 20.657 22.6440 23.99204 23.3870 24.6190 60.096   100
#  stringi 10.980 12.1585 13.57061 13.0790 13.7800 64.135   100
#     base 10.766 11.9185 13.69714 13.0665 13.8035 87.226   100

(在这种情况下,使基数R大约与stringi一样快,而比stringr快一点)。

(我很生气pasteNA转换为"NA",尽管那是already been addressed here on SO。)