在 R 中分割一个巨大的字符串的有效方法
Efficient way to split a huge string in R
我有一个巨大的字符串 (> 500MB),实际上它是一本完整的书 collection。我在另一个数据框中有一些元信息,例如页码、(不同的)作者和标题。我尝试检测我的巨大字符串中的标题字符串并按标题拆分它。我假设标题是唯一的。
数据如下所示:
mystring <- "Lorem ipsum dolor sit amet, sollicitudin duis maecenas habitasse ultrices aenean tempus"
# a dataframe of meta data, e.g. page numbers and titles
mydf <- data.frame(page = c(1, 2),
title = c( "Lorem", "maecenas"))
mydf
page title
1 1 Lorem
2 2 vivamus
mygoal <- mydf # text that comes after the title
mygoal$text <- c("ipsum dolor sit amet, sollicitudin duis", "habitasse ultrices aenean tempus")
mygoal
page title text
1 1 Lorem ipsum dolor sit amet, sollicitudin duis
2 2 vivamus habitasse ultrices aenean tempus
如何拆分字符串,使两个标题之间的所有内容成为第一个文本,第二个标题之后和第三个标题之前的所有内容成为第二个文本元素 - 以最有效的方式。
我们可以使用strsplit
mygoal$text <- trimws(strsplit(mystring,
paste(mydf$title, collapse = "|"))[[1]][-1])
-输出
> mygoal
page title text
1 1 Lorem ipsum dolor sit amet, sollicitudin duis
2 2 maecenas habitasse ultrices aenean tempus
如果您想以管道 tidyverse 方式进行操作,您可以尝试使用 stringr::str_extract
和一些正则表达式:
library(dplyr)
library(stringr)
library(glue)
mydf |>
mutate(next_title = lead(title, default = "$")) |>
mutate(text = str_extract(mystring, glue::glue("(?<={title}\s?)(.*)(?:{next_title})"))) |>
select(-next_title)
产量:
page title text
1 1 Lorem ipsum dolor sit amet, sollicitudin duis
2 2 maecenas habitasse ultrices aenean tempus
如果性能是一个问题,与 data.table
类似的方法是:
library(data.table)
library(stringr)
library(glue)
mydt <- setDT(mydf)
mydt[, next_title :=shift(title, fill = "$", type = "lead")][
,text := str_extract(..mystring, glue_data(.SD,"(?<={title}\s?)(.*)(?={next_title})"))][,
!("next_title")]
导致:
page title text
1: 1 Lorem ipsum dolor sit amet, sollicitudin duis
2: 2 maecenas habitasse ultrices aenean tempus
编辑
添加了更好的性能选项:
通常,str_split
或 str_split_fixed
比 str_extract
更快。
str_split
的问题是具有许多备用管道的正则表达式也会减慢该过程,因此另一种解决方案是先用一些固定的字符串替换字符串中的所有标题,然后分裂那些。另一件可以加快拆分速度的事情是使用 str_split_fixed
和 pre-assign 要处理的拆分数。
# create named character vector for str_replace_all function
split_at <- rep("@@",nrow(mydf))
names(split_at) <- mydf$title
mystring <- str_replace_all(mystring, split_at)
# used fixed in str_split
mydf$text <- str_split(mystring,fixed("@@ "))[[1]][-1]
# Alternative (maybe faster) define number of splits by nrow
mydf$text <- str_split_fixed(mystring,fixed("@@ "), n = nrow(mydf)+1)[,-1]
## using str_split_fixed in data.table
mydt <- setDT(mydf)
mydt[, text :=
str_split_fixed(mystring,fixed("@@ "), nrow(mydt)+1)[,-1]
我有一个巨大的字符串 (> 500MB),实际上它是一本完整的书 collection。我在另一个数据框中有一些元信息,例如页码、(不同的)作者和标题。我尝试检测我的巨大字符串中的标题字符串并按标题拆分它。我假设标题是唯一的。
数据如下所示:
mystring <- "Lorem ipsum dolor sit amet, sollicitudin duis maecenas habitasse ultrices aenean tempus"
# a dataframe of meta data, e.g. page numbers and titles
mydf <- data.frame(page = c(1, 2),
title = c( "Lorem", "maecenas"))
mydf
page title
1 1 Lorem
2 2 vivamus
mygoal <- mydf # text that comes after the title
mygoal$text <- c("ipsum dolor sit amet, sollicitudin duis", "habitasse ultrices aenean tempus")
mygoal
page title text
1 1 Lorem ipsum dolor sit amet, sollicitudin duis
2 2 vivamus habitasse ultrices aenean tempus
如何拆分字符串,使两个标题之间的所有内容成为第一个文本,第二个标题之后和第三个标题之前的所有内容成为第二个文本元素 - 以最有效的方式。
我们可以使用strsplit
mygoal$text <- trimws(strsplit(mystring,
paste(mydf$title, collapse = "|"))[[1]][-1])
-输出
> mygoal
page title text
1 1 Lorem ipsum dolor sit amet, sollicitudin duis
2 2 maecenas habitasse ultrices aenean tempus
如果您想以管道 tidyverse 方式进行操作,您可以尝试使用 stringr::str_extract
和一些正则表达式:
library(dplyr)
library(stringr)
library(glue)
mydf |>
mutate(next_title = lead(title, default = "$")) |>
mutate(text = str_extract(mystring, glue::glue("(?<={title}\s?)(.*)(?:{next_title})"))) |>
select(-next_title)
产量:
page title text
1 1 Lorem ipsum dolor sit amet, sollicitudin duis
2 2 maecenas habitasse ultrices aenean tempus
如果性能是一个问题,与 data.table
类似的方法是:
library(data.table)
library(stringr)
library(glue)
mydt <- setDT(mydf)
mydt[, next_title :=shift(title, fill = "$", type = "lead")][
,text := str_extract(..mystring, glue_data(.SD,"(?<={title}\s?)(.*)(?={next_title})"))][,
!("next_title")]
导致:
page title text
1: 1 Lorem ipsum dolor sit amet, sollicitudin duis
2: 2 maecenas habitasse ultrices aenean tempus
编辑
添加了更好的性能选项:
通常,str_split
或 str_split_fixed
比 str_extract
更快。
str_split
的问题是具有许多备用管道的正则表达式也会减慢该过程,因此另一种解决方案是先用一些固定的字符串替换字符串中的所有标题,然后分裂那些。另一件可以加快拆分速度的事情是使用 str_split_fixed
和 pre-assign 要处理的拆分数。
# create named character vector for str_replace_all function
split_at <- rep("@@",nrow(mydf))
names(split_at) <- mydf$title
mystring <- str_replace_all(mystring, split_at)
# used fixed in str_split
mydf$text <- str_split(mystring,fixed("@@ "))[[1]][-1]
# Alternative (maybe faster) define number of splits by nrow
mydf$text <- str_split_fixed(mystring,fixed("@@ "), n = nrow(mydf)+1)[,-1]
## using str_split_fixed in data.table
mydt <- setDT(mydf)
mydt[, text :=
str_split_fixed(mystring,fixed("@@ "), nrow(mydt)+1)[,-1]