R:使用for循环查找另一个字符串旁边的特定字符串

R: find a specific string next to another string with for loop

我在单个向量中有一部小说的文本,它已按单词拆分 novel.vector.words 我正在寻找字符串 "blood of" 的所有实例。然而,由于向量是按单词分割的,每个单词都是它自己的字符串,我不知道在向量中搜索相邻的字符串。

我对 for 循环的作用有基本的了解,并且按照教科书上的一些说明,我可以使用这个 for 循环来定位 "blood" 的所有位置及其周围的上下文来创建一个选项卡-划定的KWIC显示(上下文中的关键词)。

node.positions <- grep("blood", novel.vector.words)

output.conc <- "D:/School/U Alberta/Classes/Winter 2019/LING 603/dracula_conc.txt"
cat("LEFT CONTEXT\tNODE\tRIGHT CONTEXT\n", file=output.conc) # tab-delimited header

#This establishes the range of how many words we can see in our KWIC display
context <- 10 # specify a window of ten words before and after the match

for (i in 1:length(node.positions)){ # access each match...
  # access the current match
  node <- novel.vector.words[node.positions[i]]
  # access the left context of the current match
  left.context <- novel.vector.words[(node.positions[i]-context):(node.positions[i]-1)]
  # access the right context of the current match
  right.context <- novel.vector.words[(node.positions[i]+1):(node.positions[i]+context)]
  # concatenate and print the results
  cat(left.context,"\t", node, "\t", right.context, "\n", file=output.conc, append=TRUE)}

但是我不确定该怎么做,是使用 if 语句之类的东西来仅捕获 "blood" 后跟 "of" 的实例。我需要在 for 循环中使用另一个变量吗?我想让它做的基本上是对于它找到的每个 "blood" 实例,我想看看紧跟在它后面的单词是否是 "of"。我希望循环找到所有这些实例并告诉我向量中有多少。

您可以使用 dplyr::lead 创建索引以匹配 'of' 之后的 'blood':

library(dplyr)

novel.vector.words <- c("blood", "of", "blood", "red", "blood", "of", "blue", "blood")

which(grepl("blood", novel.vector.words) & grepl("of", lead(novel.vector.words)))

[1] 1 5

回复评论中的问题:

这当然可以通过基于循环的方法来完成,但是当已经有更好地设计和优化的包来完成文本挖掘任务中的繁重工作时,重新发明轮子没有什么意义。

下面是一个示例,说明如何使用 tidytext 程序包查找 'blood' 和 'of' 这两个词在 Bram Stoker 的《德古拉》中出现在五个词内的频率。

library(tidytext)
library(dplyr)
library(stringr)

## Read Dracula into dataframe and add explicit line numbers
fulltext <- data.frame(text=readLines("https://www.gutenberg.org/ebooks/345.txt.utf-8", encoding = "UTF-8"), stringsAsFactors = FALSE) %>%
  mutate(line = row_number())

## Pair of words to search for and word distance
word1 <- "blood"
word2 <- "of"
word_distance <- 5

## Create ngrams using skip_ngrams token
blood_of <- fulltext %>% 
  unnest_tokens(output = ngram, input = text,  token = "skip_ngrams", n = 2, k = word_distance - 1) %>%
  filter(str_detect(ngram, paste0("\b", word1, "\b")) & str_detect(ngram, paste0("\b", word2, "\b"))) 

## Return count
blood_of %>%
  nrow

[1] 54

## Inspect first six line number indices
head(blood_of$line)

[1]  999 1279 1309 2192 3844 4135