在 R 中对非常大的数据集进行排序

Moh*_*hit 10 r data.table

我有这个向量,我想对其进行排序。

v1<-c(1,10,2,6,8,1,3,5,"a","ab","c","d","aa","abc","a a","a bc")

然而,向量中同时包含数字和字符。所以我需要在字符之后进行数字排序。代码library(gtools); mixedsort(v1)完全按照要求解决了目的。

但我将其应用于大约 300 万个数据集。所以它效率不高,我需要一个可以更快处理它的代码。

解决方案应该是这样的。

> mixedsort(v1)
 [1] "1"    "1"    "2"    "3"    "5"    "6"    "8"    "10"   "a"    "a a"  "a bc" "aa"   "ab"   "abc"  "c"    "d"  
Run Code Online (Sandbox Code Playgroud)

多谢

Jon*_*ing 11

奇怪的是,这种笨拙的 dplyr/readr 方法比 dplyr/readr 方法快 27 倍mixedsort和 3 倍stringr::str_sort,因此很明显还有更多空间可以更快地完成此操作。

从那时起,我尝试了mixed_sort2@one,它通常会快一点。更快的方法仍然是在我原来的方法中使用as.numeric,以获得大约 100 倍的速度mixedsort

# fake data, 3 million rows of characters and numbers
v1 <- sample(c(1:99, LETTERS), 3E6, replace = TRUE)

library(dplyr)
df_parse <- function(a) {
  data.frame(a) %>%
    mutate(num = readr::parse_number(a)) %>% # 4x faster if we use `as.numeric` instead
    arrange(num, a) %>%
    pull(a)
}
Run Code Online (Sandbox Code Playgroud)

编辑:从评论@one's添加

mixed_sort2 <- function(vec){   
  numeric_sort <- sort(as.numeric(vec))
  character_sort <- sort(vec[is.na(as.numeric(vec))])
  c(numeric_sort,character_sort)
}
Run Code Online (Sandbox Code Playgroud)

使用 dplyr 方法 + as.numeric 甚至更快:

df_asnumeric <- function(a) {
  data.frame(a) %>%
    mutate(num = as.numeric(a)) %>%
    arrange(num, a) %>%
    pull(a)
}
Run Code Online (Sandbox Code Playgroud)
microbenchmark::microbenchmark(
  gtools::mixedsort(v1),
  stringr::str_sort(v1, numeric = TRUE),
  df_parse(v1),
  mixed_sort2(v1),
  df_asnumeric(v1),
  times = 10, check = 'identical'
)

Unit: milliseconds
                                  expr        min         lq       mean     median         uq       max neval
                 gtools::mixedsort(v1) 80676.6222 81825.6986 84672.9726 83671.3667 87335.5948 92225.717    10
 stringr::str_sort(v1, numeric = TRUE)  4309.6739  4327.6529  4371.6771  4373.5337  4411.2573  4450.610    10
                          df_parse(v1)   777.4925  1031.4233  1133.8790  1052.9858  1073.2195  1683.851    10
                       mixed_sort2(v1)  3505.1529  3539.8577  3747.5667  3613.3492  4033.8569  4141.554    10
                      df_asnumeric(v1)   619.2090   635.7193   812.5554   864.3629   908.5028  1026.983    10
Run Code Online (Sandbox Code Playgroud)