我有一个股票代码的字符向量,其中股票代码名称连接到该股票代码所基于的国家/地区:country_name / ticker_name。我试图拆分每个字符串并从'/'后面删除所有内容,返回仅有股票名称的字符向量。这是一个示例向量:
sample_string <- c('US/SPY', 'US/AOL', 'US/MTC', 'US/PHA', 'US/PZI',
'US/AOL', 'US/BRCM')
我最初的想法是使用stringr库。我对这个软件包没有任何经验,但这就是我的尝试:
library(stringr)
split_string <- str_split(sample_string, '/')
但我不确定如何仅将每个列表的第二个元素作为单个向量返回。
我如何在大字符向量(约1.05亿条目)上执行此操作?
答案 0 :(得分:3)
这里有一些基准,包括@David Arenburg建议的所有方法,以及使用str_extract
包中的stringr
的另一种方法。
sample_string <- rep(sample_string, 1000000)
library(data.table); library(stringr)
s1 <- function() sub(".*/(.*)", "\\1", sample_string)
s2 <- function() sub(".*/", "", sample_string)
s3 <- function() str_extract(sample_string, "(?<=/)(.*)")
s4 <- function() tstrsplit(sample_string, "/", fixed = TRUE)[[2]]
length(sample_string)
# [1] 7000000
identical(s1(), s2())
# [1] TRUE
identical(s1(), s3())
# [1] TRUE
identical(s1(), s4())
# [1] TRUE
microbenchmark::microbenchmark(s1(), s2(), s3(), s4(), times = 5)
# Unit: seconds
# expr min lq mean median uq max neval
# s1() 3.916555 3.917370 4.046708 3.923246 3.925184 4.551184 5
# s2() 3.584694 3.593755 3.726922 3.610284 3.646449 4.199426 5
# s3() 3.051398 3.062237 3.354410 3.138080 3.722347 3.797985 5
# s4() 1.908283 1.964223 2.349522 2.117521 2.760612 2.996971 5
tstrsplit
方法最快。
<强>更新强>:
从@Frank添加另一个方法,这种比较并不严格准确,这取决于实际数据,如果上面生成sample_string
时存在大量重复案例,则优势非常明显:
s5 <- function() setDT(list(sample_string))[, v := tstrsplit(V1, "/", fixed = TRUE)[[2]], by=V1]$v
identical(s1(), s5())
# [1] TRUE
microbenchmark::microbenchmark(s1(), s2(), s3(), s4(), s5(), times = 5)
# Unit: milliseconds
# expr min lq mean median uq max neval
# s1() 3905.97703 3913.264 3922.8540 3913.4035 3932.2680 3949.3575 5
# s2() 3568.63504 3576.755 3713.7230 3660.5570 3740.8252 4021.8426 5
# s3() 3029.66877 3032.898 3061.0584 3052.6937 3086.9714 3103.0604 5
# s4() 1322.42430 1679.475 1985.5440 1801.9054 1857.8056 3266.1101 5
# s5() 82.71379 101.899 177.8306 121.6682 209.0579 373.8141 5
答案 1 :(得分:2)
关于您的问题的一些有用的说明:首先,str_split_fixed
包中有一个stringr
函数,通过调用lapply来执行您希望它执行的操作。
library(data.table); library(stringr)
sample_string <- c('US/SPY', 'US/AOL', 'US/MTC', 'US/PHA', 'US/PZI',
'US/AOL', 'US/BRCM')
sample_string <- rep(sample_string, 1e5)
split_string <- str_split_fixed(sample_string, '/', 2)[,2]
它通过调用stringi::stri_split_fixed
起作用,与
do.call("c", lapply(str_split(sample_string, '/'),"[[",2))
其次,考虑提取列表中每个第二个元素的另一种方法是完全执行tstrsplit
内部正在做的事情。
transpose(strsplit(sample_string, "/", fixed = T))[[2]]
总的来说,上述内容应该比调用tstrsplit
略快。当然,这可能不值得打字,但它有助于了解该功能的作用。
library(data.table); library(stringr)
s4 <- function() tstrsplit(sample_string, "/", fixed = TRUE)[[2]]
s5 <- function() transpose(strsplit(sample_string, "/", fixed = T))[[2]]
identical(s4(), s5())
microbenchmark::microbenchmark(s4(), s5(), times = 20)
microbenchmark::microbenchmark(s4(), s5(), times = 20)
Unit: milliseconds
expr min lq mean median uq max neval
s4() 161.0744 193.3611 255.8136 234.9945 271.6811 434.7992 20
s5() 140.8569 176.5600 233.3570 194.1676 251.7921 420.3431 20
关于第二种方法,简而言之,转换这个长度为700万的列表,每个包含2个元素,将结果转换为长度为2的列表,每个列表包含700万个元素。然后,您将提取此列表的第二个元素。