Here is a base R solution. It is a simplification of the question's code and it is twice as fast. This increased speed comes from avoiding the creation of a data.frame, df1, followed by extraction operations, which in the case of data.frames are always slow.
In the 2nd strsplit, perl = TRUE was replaced by fixed = TRUE, a further speed-up thanks to akrun's comment.
The three solutions (OP's, this one and akrun's) are rewritten in the form of functions, with timings at the end.
cnauber <- function(X){
s <- strsplit(X$C1, split = "(; (?=\\[))",perl=TRUE)
df1 <- data.frame(
UT= rep(X$UT, sapply(s, length)),
AU=gsub('] .*', ']', unlist(s)),
C1=gsub('.*\\]', '', unlist(s))
)
s1 <-strsplit(df1$C1, split = "; ",perl=TRUE)
data.frame(
UT= rep(df1$UT, sapply(s1, length)),
AU= rep(df1$AU, sapply(s1, length)),
C1=unlist(s1)
)
}
rui <- function(X){
s <- strsplit(X$C1, split = "(; (?=\\[))", perl = TRUE)
ut <- rep(X$UT, lengths(s))
au <- sub('] .*', ']', unlist(s))
c1 <- sub('.*\\]', '', unlist(s))
s1 <- strsplit(c1, split = "; ", fixed = TRUE)
data.frame(
UT = rep(ut, lengths(s1)),
AU = rep(au, lengths(s1)),
C1 = unlist(s1)
)
}
library(dplyr)
library(tidyr)
library(stringr)
akrun <- function(X){
X %>%
separate_rows(C1, sep=";\\s*(?=\\[)") %>%
mutate(AU = str_extract(C1, "\\[[^]]+\\]"),
C1 = str_extract_all(C1, 'string\\s*[0-9.]+')) %>%
unnest(c(C1)) %>%
select(UT, AU, C1)
}
The first benchmark is with the original 3 rows data.
mb <- microbenchmark(
cnauber = cnauber(df),
rui = rui(df),
akrun = akrun(df)
)
print(mb, order = "median")
#Unit: microseconds
# expr min lq mean median uq max neval cld
# rui 522.003 793.2365 1019.390 832.8795 993.800 18186.66 100 a
# cnauber 1062.187 1603.5655 1858.867 1643.8895 1816.374 20068.48 100 a
# akrun 19931.267 29093.6995 31774.619 29780.3750 31086.222 175779.06 100 b
The second benchmark is with a larger data set.
for(i in 1:10) df <- rbind(df, df)
mb <- microbenchmark(
cnauber = cnauber(df),
rui = rui(df),
akrun = akrun(df)
)
print(mb, order = "median")
#Unit: milliseconds
# expr min lq mean median uq max neval cld
# rui 32.79471 45.00103 45.73348 45.80887 47.14947 70.10428 100 a
# cnauber 57.42609 70.17960 75.93042 73.73240 80.90393 105.26087 100 b
# akrun 483.04227 528.21140 566.06477 558.65710 601.27015 785.15709 100 c