阅读 R 语料库中每个文档的前两行
Read the first two lines of each document in a corpus in R
我无法弄清楚如何阅读 R 语料库中每个文档的前两行。前两行包含我要分析的新闻文章的标题。我想在标题(而不是每个文本的其余部分)中搜索单词 'abortion.'
这是我创建语料库的代码:
myCorp <- corpus(readtext(file='~/R/win-library/3.3/quanteda/Abortion/1972/*'))
我试过在 for 循环中使用 readLines:
for (mycorp in myCorp) {
titles <- readLines(mycorp, n = 2)
write.table(mycorp, "1972_text_P.txt", sep="\n\n", append=TRUE)
write.table(titles, "1972_text_P.txt", append=TRUE)
}
readLines(mycorp, n = 2) 出错:'con' 不是连接
我有意没有创建 DFM,因为我想将 465 个文件作为单个文档保存在语料库中。如何从文章文本中获取标题?或者,理想情况下,我如何只在每个文档的前两行中搜索关键字(堕胎)并创建一个文件,其中只包含那些带有关键字的标题?感谢您对此提供的所有帮助。
readLines
函数需要一个连接对象作为参数。因此,由于 corpus
函数没有 return 连接,您需要在循环中创建到语料库中字符串的连接。
myCorp <- Corpus(quanteda::data_corpus_inaugural)
for (text in myCorp$documents$texts) {
con <- textConnection(text,)
first_lines <- readLines(con, n = 2)
close.connection(con)
# Test if the word "speaker" is in the two lines
if(any(grepl(pattern = "speaker",x = first_lines, ignore.case = T))){
print(first_lines)
}
}
我建议两个选项:
正则表达式替换只保留前两行
如果您的前两行包含您需要的内容,那么只需使用提取前两行的正则表达式来提取它们。这比循环更快。
@rconradin 的解决方案有效,但正如您将在 ?corpus 中注意到的那样,我们强烈反对直接访问语料库对象的内部结构(因为它很快就会改变)。不循环也更快。
# test corpus for demonstration
testcorp <- corpus(c(
d1 = "This is doc1, line 1.\nDoc1, Line 2.\nLine 3 of doc1.",
d2 = "This is doc2, line 1.\nDoc2, Line 2.\nLine 3 of doc2."
))
summary(testcorp)
## Corpus consisting of 2 documents.
##
## Text Types Tokens Sentences
## d1 12 17 3
## d2 12 17 3
现在只用前两行覆盖文本。 (这也会丢弃第二个换行符,如果你想保留它,只需将它移到第一个捕获组即可。)
texts(testcorp) <-
stringi::stri_replace_all_regex(texts(testcorp), "(.*\n.*)(\n).*", "")
## Corpus consisting of 2 documents.
##
## Text Types Tokens Sentences
## d1 10 12 2
## d2 10 12 2
texts(testcorp)
## d1 d2
## "This is doc1, line 1.\nDoc1, Line 2." "This is doc2, line 1.\nDoc2, Line 2."
使用 corpus_segment()
:
另一种解决方案是使用 corpus_segment()
:
testcorp2 <- corpus_segment(testcorp, what = "other", delimiter = "\n",
valuetype = "regex")
summary(testcorp2)
## Corpus consisting of 6 documents.
##
## Text Types Tokens Sentences
## d1.1 7 7 1
## d1.2 5 5 1
## d1.3 5 5 1
## d2.1 7 7 1
## d2.2 5 5 1
## d2.3 5 5 1
# get the serial number from each docname
docvars(testcorp2, "sentenceno") <-
as.integer(gsub(".*\.(\d+)", "\1", docnames(testcorp2)))
summary(testcorp2)
## Corpus consisting of 6 documents.
##
## Text Types Tokens Sentences sentenceno
## d1.1 7 7 1 1
## d1.2 5 5 1 2
## d1.3 5 5 1 3
## d2.1 7 7 1 1
## d2.2 5 5 1 2
## d2.3 5 5 1 3
testcorp3 <- corpus_subset(testcorp2, sentenceno <= 2)
texts(testcorp3)
## d1.1 d1.2 d2.1 d2.2
## "This is doc1, line 1." "Doc1, Line 2." "This is doc2, line 1." "Doc2, Line 2."
我无法弄清楚如何阅读 R 语料库中每个文档的前两行。前两行包含我要分析的新闻文章的标题。我想在标题(而不是每个文本的其余部分)中搜索单词 'abortion.'
这是我创建语料库的代码:
myCorp <- corpus(readtext(file='~/R/win-library/3.3/quanteda/Abortion/1972/*'))
我试过在 for 循环中使用 readLines:
for (mycorp in myCorp) {
titles <- readLines(mycorp, n = 2)
write.table(mycorp, "1972_text_P.txt", sep="\n\n", append=TRUE)
write.table(titles, "1972_text_P.txt", append=TRUE)
}
readLines(mycorp, n = 2) 出错:'con' 不是连接
我有意没有创建 DFM,因为我想将 465 个文件作为单个文档保存在语料库中。如何从文章文本中获取标题?或者,理想情况下,我如何只在每个文档的前两行中搜索关键字(堕胎)并创建一个文件,其中只包含那些带有关键字的标题?感谢您对此提供的所有帮助。
readLines
函数需要一个连接对象作为参数。因此,由于 corpus
函数没有 return 连接,您需要在循环中创建到语料库中字符串的连接。
myCorp <- Corpus(quanteda::data_corpus_inaugural)
for (text in myCorp$documents$texts) {
con <- textConnection(text,)
first_lines <- readLines(con, n = 2)
close.connection(con)
# Test if the word "speaker" is in the two lines
if(any(grepl(pattern = "speaker",x = first_lines, ignore.case = T))){
print(first_lines)
}
}
我建议两个选项:
正则表达式替换只保留前两行
如果您的前两行包含您需要的内容,那么只需使用提取前两行的正则表达式来提取它们。这比循环更快。
@rconradin 的解决方案有效,但正如您将在 ?corpus 中注意到的那样,我们强烈反对直接访问语料库对象的内部结构(因为它很快就会改变)。不循环也更快。
# test corpus for demonstration
testcorp <- corpus(c(
d1 = "This is doc1, line 1.\nDoc1, Line 2.\nLine 3 of doc1.",
d2 = "This is doc2, line 1.\nDoc2, Line 2.\nLine 3 of doc2."
))
summary(testcorp)
## Corpus consisting of 2 documents.
##
## Text Types Tokens Sentences
## d1 12 17 3
## d2 12 17 3
现在只用前两行覆盖文本。 (这也会丢弃第二个换行符,如果你想保留它,只需将它移到第一个捕获组即可。)
texts(testcorp) <-
stringi::stri_replace_all_regex(texts(testcorp), "(.*\n.*)(\n).*", "")
## Corpus consisting of 2 documents.
##
## Text Types Tokens Sentences
## d1 10 12 2
## d2 10 12 2
texts(testcorp)
## d1 d2
## "This is doc1, line 1.\nDoc1, Line 2." "This is doc2, line 1.\nDoc2, Line 2."
使用 corpus_segment()
:
另一种解决方案是使用 corpus_segment()
:
testcorp2 <- corpus_segment(testcorp, what = "other", delimiter = "\n",
valuetype = "regex")
summary(testcorp2)
## Corpus consisting of 6 documents.
##
## Text Types Tokens Sentences
## d1.1 7 7 1
## d1.2 5 5 1
## d1.3 5 5 1
## d2.1 7 7 1
## d2.2 5 5 1
## d2.3 5 5 1
# get the serial number from each docname
docvars(testcorp2, "sentenceno") <-
as.integer(gsub(".*\.(\d+)", "\1", docnames(testcorp2)))
summary(testcorp2)
## Corpus consisting of 6 documents.
##
## Text Types Tokens Sentences sentenceno
## d1.1 7 7 1 1
## d1.2 5 5 1 2
## d1.3 5 5 1 3
## d2.1 7 7 1 1
## d2.2 5 5 1 2
## d2.3 5 5 1 3
testcorp3 <- corpus_subset(testcorp2, sentenceno <= 2)
texts(testcorp3)
## d1.1 d1.2 d2.1 d2.2
## "This is doc1, line 1." "Doc1, Line 2." "This is doc2, line 1." "Doc2, Line 2."