为什么substr函数在数据帧中速度慢?

时间:2018-12-30 10:33:20

标签: r performance substr

我正在从一个具有700,000行的数据框中提取子字符串。

例如,假设我有一个变量ord,它是大小为1 X 700,000的数据帧。 我正在使用substr(ord[, 1], 23, 36),但速度很慢。有人可以建议其他方法或改进吗?

2 个答案:

答案 0 :(得分:2)

您确定没有小标题而不是data.frame吗?

对于一元变量,使用[, 1]不会做任何事情,因为您将获得相同的一元变量。始终将data.frame或小标题视为列表(而不是矩阵),并使用[[1]]将第一个变量作为矢量访问。

在计时方面(数据少10倍):

ord_ch <- rep(replicate(700, paste(sample(letters, 40, TRUE), collapse = "")), 100)
ord_df <- data.frame(xcol = ord_ch, stringsAsFactors = FALSE)
ord_df_fct <- data.frame(xcol = ord_ch, stringsAsFactors = TRUE)
ord_tbl <- tibble::tibble(xcol = ord_ch)

microbenchmark::microbenchmark(
  substr(ord_ch, 23, 36),
  substr(ord_df[, 1], 23, 36),
  substr(ord_df_fct[, 1], 23, 36),
  substr(ord_tbl[, 1], 23, 36),
  times = 10
)

基准测试结果

Unit: milliseconds
                            expr         min          lq        mean      median
          substr(ord_ch, 23, 36)    8.807504    8.921520    9.253258    9.321168
     substr(ord_df[, 1], 23, 36)    8.711323    8.775754    9.030802    8.965194
 substr(ord_df_fct[, 1], 23, 36)    9.337599    9.544920   10.065594    9.595284
    substr(ord_tbl[, 1], 23, 36) 1433.387037 1446.136184 1456.639754 1453.826835
          uq         max neval
    9.391774   10.077075    10
    9.167970    9.713614    10
   10.016577   12.173109    10
 1460.824234 1494.942769    10

答案 1 :(得分:0)

让我们尝试使用basestringi来对data.frame和character进行子字符串操作

# install.packages("rbenchmark")
# install.packages("stringi")

library(rbenchmark)
library(stringi)

ord_ch <- rep(paste0(sample(c(letters,LETTERS), 40), collapse = ""), 700000)
ord_df <- data.frame(ord_ch, stringsAsFactors = F)

# rbenchmark package can compare elapsed time by running your code several (100) times.
benchmark("dataframe" = substr(ord_df[, 1], 23, 36)
          , "character" = substr(ord_ch, 23, 36)
          , "stri_character" =  stringi::stri_sub(ord_ch, 23, 36)
          , "stri_dataframe" =  stringi::stri_sub(ord_df[, 1], 23, 36)
          , replications = 100) 

这是我系统的结果。 data.frame比字符向量慢0.5秒。您可以考虑自己的情况,是否值得更改类型。

#             test replications elapsed relative user.self sys.self user.child sys.child
#       character          100    7.61    1.000      7.37     0.19         NA        NA
#       dataframe          100    8.10    1.064      7.71     0.28         NA        NA
#  stri_character          100    7.88    1.035      7.15     0.55         NA        NA
#  stri_dataframe          100    8.16    1.072      6.94     0.64         NA        NA