我有一串由随机字母、空格和句点组成的字符串。我想从中获取每个第n个值(例如每10个)。我的想法是,如果我可以转置它,那么我就可以使用行号来选择每个第n个值。感谢您的任何帮助!
string <- "hutmnycdsldzlkt.ytairuaypk dq.gubgp hyfjuwvpcdmvqxfcuhapnx"
为了跟进 OP 的想法("使用行号"),将字符串分割,填充一个有10行的矩阵,选择第一行。
matrix(strsplit(x, "")[[1]], nrow = 10)[1, ]
# [1] "h" "d" "r" "." "j" "x"
rawToChar(charToRaw(x)[c(TRUE, rep(FALSE, 9))])
# [1] "hdr.jx"
seq
来获取元素。v1 <- strsplit(string, "")[[1]]
v1[seq(1, by = 10, length(v1))]
#[1] "h" "d" "r" "." "j" "x"
library(stringr)
str_replace_all(string, "(.).{1,9}", "\\1")
#[1] "hdr.jx"
或者使用 glue
使其动态化
n <- 9
str_replace_all(string, glue::glue("(.).{1,[n]}",
.open = '[', .close = ']'), "\\1")
#[1] "hdr.jx"
substring
函数需要一个由first=
和last=
组成的向量,因此我们可以构造一个合适的序列并从那里开始。
func <- function(x, n, start = 1) {
vapply(x, function(z) {
i <- seq.int(start, nchar(z), by = n)
i <- i[i > 0]
paste(substring(x, i, i), collapse = "")
}, character(1))
}
func(string, 10)
# hutmnycdsldzlkt.ytairuaypk dq.gubgp hyfjuwvpcdmvqxfcuhapnx
# "hdr.jx"
每个10个数中(从1开始)
hutmnycdsldzlkt.ytairuaypk dq.gubgp hyfjuwvpcdmvqxfcuhapnx
12345678901234567890123456789012345678901234567890123456789
^ ^ ^ ^ ^ ^
h d r . j x
apply
变体的最大原因是为了处理字符串向量的情况,其中 substring
将能够优雅地工作。好的,这是对@r2evans答案的补充,旨在通过不必针对每个单独的值循环来加速矢量化的substring
操作。
func2 <- function(x, n, start = 1) {
mnc <- max(nchar(x))
i <- seq.int(start, mnc, by = n)
res <- paste(substring(rep(x, each=length(i)), i, i), collapse="")
fi <- findInterval(nchar(x), i)
substring(res, c(1, head(cumsum(fi),-1) + 1), cumsum(fi) )
}
对20K条数据进行快速测试:
x <- c("12345678901234567890", "09876543210987654321")
bigx <- rep(x,1e4)
system.time(func(bigx, 10, 1))
## user system elapsed
## 38.29 0.03 38.36
system.time(func2(bigx, 10, 1))
## user system elapsed
## 0.02 0.00 0.02
substring
+ seq
+ nchar
的基本R选项。substring(
string,
v <- seq(1, nchar(string), by = 10),
v
)
提供
"h" "d" "r" "." "j" "x"
vapply
函数,并通过将每个x
值与最大的i
序列多次rep
以及仅调用一次substring
函数来使其更快。类似这样:func2 <- function(x, n, start = 1) { mnc <- max(nchar(x)); i <- seq.int(start, mnc, by = n); paste(substring(rep(x, each=length(i)), i, i), collapse="") }
- thelatemailsubstring
,但事后发现超出索引会默默地变成0长度,所以这是一个不必要的预防措施。我认为你的方法肯定更简单,也更快。谢谢,@thelatemail。 - r2evans