R:提取部分长度不同的字符串
R: Extract part of string with varying length
我有一个字符串列表(非常大,数百万行),我想从中提取特定部分。
我先在分号处拆分字符串,然后提取到特定的部分。它变得有点复杂,因为有时一行有 3 个,有时有 4 个段。但是我感兴趣的部分总是最后和倒数第二个片段。
示例代码:
dataStr = c("secAlways; secExtr1; secExtr2",
"secSometimes; secAlways; secExtr1; secExtr2",
"secSometimes; secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2",
"secSometimes; secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2")
splStr <- strsplit(dataStr, ";")
extr1 <- list()
extr2 <- list()
for (i in 1:length(splStr)) {
extr1[i] <- head( tail(splStr[[i]], n=2), n=1)
extr2[i] <- tail(splStr[[i]], n = 1)
}
可以用,但是太慢了。对于如何加快速度的任何想法,我将不胜感激。我怀疑这可能是用 apply
完成的,但我无法理解它。
如果问题可能与 问题重复,则会提出问题。我认为它有点不同,因为我想提取最后两个元素并且部分的数量不同。此外,我还没有得到 vapply
的解决方案来处理我的真实样本。
我认为你最好在这里使用正则表达式:
sub(".+; (.+?); (.+?)$", "\2", dataStr)
这将获取最后一项。
sub(".+; (.+?); (.+?)$", "\1", dataStr)
这将在最后一个项目之前获取项目。
这样做可能会更快:
str_list <- lapply(splStr, tail, 2)
do.call(rbind, str_list)
[,1] [,2]
[1,] " secExtr1" " secExtr2"
[2,] " secExtr1" " secExtr2"
[3,] " secExtr1" " secExtr2"
[4,] " secExtr1" " secExtr2"
[5,] " secExtr1" " secExtr2"
[6,] " secExtr1" " secExtr2"
[7,] " secExtr1" " secExtr2"
[8,] " secExtr1" " secExtr2"
[9,] " secExtr1" " secExtr2"
[10,] " secExtr1" " secExtr2"
我们可以使用 stringi
和 vapply
来加快速度
library(stringi)
vapply(stri_split(dataStr, regex=';\s*'), function(x) tail(x, 2), character(2))
来自 stringr
的 word
解决方案,
stringr::word(dataStr, -2, -1, sep = ';')
然后您可以 strsplit
将它们作为 2 个不同的词,即
do.call(rbind, strsplit(trimws(word(dataStr, -2, -1, sep = ';')), '; '))
# [,1] [,2]
# [1,] "secExtr1" "secExtr2"
# [2,] "secExtr1" "secExtr2"
# [3,] "secExtr1" "secExtr2"
# [4,] "secExtr1" "secExtr2"
# [5,] "secExtr1" "secExtr2"
# [6,] "secExtr1" "secExtr2"
# [7,] "secExtr1" "secExtr2"
# [8,] "secExtr1" "secExtr2"
# [9,] "secExtr1" "secExtr2"
#[10,] "secExtr1" "secExtr2"
> str_list <- lapply(dataStr, tail, 2)
> do.call(rbind, str_list)
[,1]
[1,] "secAlways; secExtr1; secExtr2"
[2,] "secSometimes; secAlways; secExtr1; secExtr2"
[3,] "secSometimes; secAlways; secExtr1; secExtr2"
[4,] "secAlways; secExtr1; secExtr2"
[5,] "secAlways; secExtr1; secExtr2"
[6,] "secAlways; secExtr1; secExtr2"
[7,] "secSometimes; secAlways; secExtr1; secExtr2"
[8,] "secAlways; secExtr1; secExtr2"
[9,] "secAlways; secExtr1; secExtr2"
[10,] "secAlways; secExtr1; secExtr2"
我不确定这是否有效?
假设最后一段和倒数第二段的字符数始终相同,这可以使用 stringi
库通过以下方式实现。
我还假设您想要两个列表作为输出。
library(stringi)
dataStr = c("secAlways; secExtr1; secExtr2",
"secSometimes; secAlways; secExtr1; secExtr2",
"secSometimes; secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2",
"secSometimes; secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2")
extr1 <- as.list(stringi::stri_sub(dataStr, from=-18, to=-11))
extr2 <- as.list(stringi::stri_sub(dataStr, from= -8))
我有一个字符串列表(非常大,数百万行),我想从中提取特定部分。
我先在分号处拆分字符串,然后提取到特定的部分。它变得有点复杂,因为有时一行有 3 个,有时有 4 个段。但是我感兴趣的部分总是最后和倒数第二个片段。
示例代码:
dataStr = c("secAlways; secExtr1; secExtr2",
"secSometimes; secAlways; secExtr1; secExtr2",
"secSometimes; secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2",
"secSometimes; secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2")
splStr <- strsplit(dataStr, ";")
extr1 <- list()
extr2 <- list()
for (i in 1:length(splStr)) {
extr1[i] <- head( tail(splStr[[i]], n=2), n=1)
extr2[i] <- tail(splStr[[i]], n = 1)
}
可以用,但是太慢了。对于如何加快速度的任何想法,我将不胜感激。我怀疑这可能是用 apply
完成的,但我无法理解它。
如果问题可能与 vapply
的解决方案来处理我的真实样本。
我认为你最好在这里使用正则表达式:
sub(".+; (.+?); (.+?)$", "\2", dataStr)
这将获取最后一项。
sub(".+; (.+?); (.+?)$", "\1", dataStr)
这将在最后一个项目之前获取项目。
这样做可能会更快:
str_list <- lapply(splStr, tail, 2)
do.call(rbind, str_list)
[,1] [,2]
[1,] " secExtr1" " secExtr2"
[2,] " secExtr1" " secExtr2"
[3,] " secExtr1" " secExtr2"
[4,] " secExtr1" " secExtr2"
[5,] " secExtr1" " secExtr2"
[6,] " secExtr1" " secExtr2"
[7,] " secExtr1" " secExtr2"
[8,] " secExtr1" " secExtr2"
[9,] " secExtr1" " secExtr2"
[10,] " secExtr1" " secExtr2"
我们可以使用 stringi
和 vapply
library(stringi)
vapply(stri_split(dataStr, regex=';\s*'), function(x) tail(x, 2), character(2))
来自 stringr
的 word
解决方案,
stringr::word(dataStr, -2, -1, sep = ';')
然后您可以 strsplit
将它们作为 2 个不同的词,即
do.call(rbind, strsplit(trimws(word(dataStr, -2, -1, sep = ';')), '; '))
# [,1] [,2]
# [1,] "secExtr1" "secExtr2"
# [2,] "secExtr1" "secExtr2"
# [3,] "secExtr1" "secExtr2"
# [4,] "secExtr1" "secExtr2"
# [5,] "secExtr1" "secExtr2"
# [6,] "secExtr1" "secExtr2"
# [7,] "secExtr1" "secExtr2"
# [8,] "secExtr1" "secExtr2"
# [9,] "secExtr1" "secExtr2"
#[10,] "secExtr1" "secExtr2"
> str_list <- lapply(dataStr, tail, 2)
> do.call(rbind, str_list)
[,1]
[1,] "secAlways; secExtr1; secExtr2"
[2,] "secSometimes; secAlways; secExtr1; secExtr2"
[3,] "secSometimes; secAlways; secExtr1; secExtr2"
[4,] "secAlways; secExtr1; secExtr2"
[5,] "secAlways; secExtr1; secExtr2"
[6,] "secAlways; secExtr1; secExtr2"
[7,] "secSometimes; secAlways; secExtr1; secExtr2"
[8,] "secAlways; secExtr1; secExtr2"
[9,] "secAlways; secExtr1; secExtr2"
[10,] "secAlways; secExtr1; secExtr2"
我不确定这是否有效?
假设最后一段和倒数第二段的字符数始终相同,这可以使用 stringi
库通过以下方式实现。
我还假设您想要两个列表作为输出。
library(stringi)
dataStr = c("secAlways; secExtr1; secExtr2",
"secSometimes; secAlways; secExtr1; secExtr2",
"secSometimes; secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2",
"secSometimes; secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2",
"secAlways; secExtr1; secExtr2")
extr1 <- as.list(stringi::stri_sub(dataStr, from=-18, to=-11))
extr2 <- as.list(stringi::stri_sub(dataStr, from= -8))