Операция со строкой R: Как я могу оптимизировать этот? - PullRequest
0 голосов
/ 28 июня 2018

TL; DR: я хочу завершить каждую строку списка до заданного размера заданным символом слева. Я хочу это быстро. Смотрите код ниже и пример

У меня очень большой вектор строк, содержащий ... ну что угодно, но с максимальным (известным) количеством символов. Я хочу дополнить строки 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 голосов
/ 28 июня 2018

Если вам важна скорость, база 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, в в этом случае.)

(Я слегка раздражен, что paste преобразует NA в "NA", хотя это уже было рассмотрено здесь на SO .)

0 голосов
/ 28 июня 2018

Это зависит от внешнего пакета, но занимает 1/30 времени, которое занимает ваша функция zero_left ():

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

Редактировать 1:

Решение Base-R, которое равно кажется , вероятно, не просто так быстро:

gsub(pattern = " ", replacement = "0", sprintf("%*s", nb, trial), fixed = TRUE)

Редактировать 2:

Помня, что stringr - это просто оболочка для stringi функций, вы можете получить еще один скоростной ускоритель, используя stringi напрямую:

stringi::stri_pad_left(trial, width = nb, pad = "0")

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...