#r #for-loop #corpus
#r #for-цикл #corpus
Вопрос:
У меня есть текст романа в одном векторе, он был разделен по словам 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 CONTEXTtNODEtRIGHT CONTEXTn", 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». Я хочу, чтобы цикл нашел все эти экземпляры и сообщил мне, сколько их в моем векторе.
Ответ №1:
Вы можете создать индекс, используя dplyr::lead
для соответствия ‘of’ следующей ‘blood’:
library(dplyr)
novel.vector.words <- c("blood", "of", "blood", "red", "blood", "of", "blue", "blood")
which(grepl("blood", novel.vector.words) amp; grepl("of", lead(novel.vector.words)))
[1] 1 5
В ответ на вопрос в комментариях:
Это, безусловно, можно было бы сделать с помощью подхода, основанного на цикле, но нет особого смысла заново изобретать колесо, когда уже есть пакеты, лучше спроектированные и оптимизированные для выполнения тяжелой работы в задачах интеллектуального анализа текста.
Вот пример того, как с помощью tidytext
пакета определить, как часто слова «кровь» и «из» встречаются с интервалом в пять слов друг от друга в «Дракуле» Брэма Стокера.
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")) amp; 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
Комментарии:
1. Спасибо, это намного проще, чем цикл for. Мне все еще интересно, сделали бы вы это с помощью цикла for, поэтому я собираюсь оставить вопрос немного открытым, и я приму ваш ответ, если больше ничего не услышу. Однако у меня есть связанный с этим вопрос: что, если бы я хотел найти «of» в определенном диапазоне значений «blood»? Произнесите любое слово в пределах 5 слов слева и 5 слов справа.