ループの数を確実に最小化することで時間を短縮でき、さらにparallel
パッケージを使用することでさらに削減できます...私のアプローチは、文字列を一度分割してから、ループで並べ替えて貼り付けます:
sort_cat <- function(strings){
tmp <- strsplit(strings, split="")
tmp <- lapply(tmp, sort)
tmp <- lapply(tmp, paste0, collapse = "")
tmp <- unlist(tmp)
return(tmp)
}
sort_cat2 <- function(strings){
unlist(mcMap(function(i){
stri_join(sort(i), collapse = "")
}, stri_split_regex(strings, "|", omit_empty = TRUE, simplify = F), mc.cores = 8L))
}
> microbenchmark::microbenchmark(
+ old = sort_cat(strings[1:500000]),
+ new = sort_cat2(strings[1:500000]),
+ times = 1
+ )
Unit: seconds
expr min lq mean median uq max neval
old 9.62673395 9.62673395 9.62673395 9.62673395 9.62673395 9.62673395 1
new 5.10547437 5.10547437 5.10547437 5.10547437 5.10547437 5.10547437 1
4秒ほど剃りますが、それでもそれほど速くはありません...
編集する
さて、apply
ここで..戦略を使用してそれを手に入れました:
1)境界を分割するのではなく文字を抽出する2)結果を含む行列を作成する3)行ごとに繰り返す4)ソート5)結合する
複数のループとリストからの除外を避けます。...IGNORE:?警告は、文字列の長さが異なる場合は、以下のapply
ような空またはNAを削除する必要があります。i[!is.na(i) && nchar(i) > 0]
sort_cat3 <- function(strings){
apply(stri_extract_all_regex(strings, "\\p{L}", simplify = TRUE), 1, function(i){
stri_join(stri_sort(i), collapse = "")
})
}
> microbenchmark::microbenchmark(
+ old = sort_cat(strings[1:500000]),
+ mapping = sort_cat2(strings[1:500000]),
+ applying = sort_cat3(strings[1:500000]),
+ times = 1
+ )
Unit: seconds
expr min lq mean median uq max neval
old 10.35101934 10.35101934 10.35101934 10.35101934 10.35101934 10.35101934 1
mapping 5.12771799 5.12771799 5.12771799 5.12771799 5.12771799 5.12771799 1
applying 3.97775326 3.97775326 3.97775326 3.97775326 3.97775326 3.97775326 1
10.3秒から3.98秒まで