我正在从一个具有700,000行的数据框中提取子字符串。
例如,假设我有一个变量ord
,它是大小为1 X 700,000的数据帧。
我正在使用substr(ord[, 1], 23, 36)
,但速度很慢。有人可以建议其他方法或改进吗?
答案 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)
让我们尝试使用base
和stringi
来对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