如何使用 readtext 将多个 JSON 文件加载到 quanteda 语料库中?
How to load multiple JSON files into a quanteda corpus using readtext?
我正在尝试使用 readtext
从新闻网站将大量 JSON 文件加载到 quanteda 语料库中。为了简化这个过程,JSON 文件都在工作目录中。但我也在他们自己的目录中尝试过。
- 当使用
c()
创建一个显式定义一小部分文件的变量时,readtext
可以正常工作,并且可以使用 corpus()
.[=114= 正确创建语料库]
- 当尝试使用
list.files()
创建变量以列出所有 +1500 JSON 文件时 readtext
无法按预期工作,出现 return 错误,并且没有创建语料库。
我试图检查两种定义文本集的方法(即 c()
和 list.files()
)以及 paste0()
.
的结果
# Load libraries
library(readtext)
library(quanteda)
# Define a set of texts explicitly
a <- c("border_2020_05_10__1589150513.json","border_2020_05_10__1589143358.json","border_2020_05_07__1589170960.json")
# This produces a corpus
extracted_texts <- readtext(a, text_field = "maintext")
my_corpus <- corpus(extracted_texts)
# Define a set of all texts in working directory
b <- list.files(pattern = "*.json", full.names = F)
# This, which I hope to use, produces an error
extracted_texts <- readtext(b, text_field = "maintext")
my_corpus <- corpus(extracted_texts)
extracted_texts <- readtext(b, text_field = "maintext")
产生的错误如下
File doesn't contain a single valid JSON object.
Error: This JSON file format is not supported.
这很令人费解,因为使用 a
调用的相同文件不会产生错误。我 validated several of the JSON files which in every case returned VALID (RFC 8259), the IETF standard 为 JSON.
检查 a
和 b
之间的差异:
typeof()
returns "character"
对于 a
和 b
.
is.vector()
和 is.atomic()
return TRUE
两者。
is.list()
returns FALSE
两个。
- 它们在 RStudio 中和在控制台中调用时看起来相似
我真的很困惑为什么 a
有效而 b
无效。
最后,尝试完全模仿 readtext documentation 所采用的程序,还尝试了以下操作:
# XXXX = my username
data_dir <- file.path("C:/Users/XXXX/Documents/R/")
d <- readtext(paste0(data_dir, "/corpus_linguistics/*.json"), text_field = "maintext")
这也return编辑了错误
File doesn't contain a single valid JSON object.
Error: This JSON file format is not supported.
此时我被难住了。提前感谢您对如何前进的任何见解。
解决方案和总结
- 不干净的数据: 一些输入 JSON 文件有空
main_text
字段。这些对分析没有用,应该删除。所有文件都包含一个名为 "title_rss"
的 JSON 字段,该字段为空。这可以通过目录级查找和替换为 Notepad ++,或者可能是 R 或 Python 来消除,尽管我仍然缺乏这方面的技能。此外,文件不是 UTF-8 编码,已通过 Codepage Converter. 解决
- 调用目录字符串的方法: readtext How to Use documentation and several third party tutorials中使用了
list.files()
方法。此方法适用于 *.txt 文件,但由于某些原因,它似乎不适用于这些特定的 JSON 文件。一旦 JSON 文件被正确清理和编码,下面的方法就可以正常工作。如果 data_dir
包装在 list.files()
函数中,则会产生以下错误:
Error in list_files(file, ignore_missing, TRUE, verbosity) : File '' does not exist.
我不确定为什么会这样,但是对于这些 JSON 文件,将其保留在外面是有效的。
# Load libraries
library(readtext)
library(quanteda)
# Define a set of texts explicitly
data_dir <- "C:/Users/Nathan/Documents/R/corpus_linguistics/"
extracted_texts <- readtext(paste0(data_dir, "texts_unmodified/*.json"), text_field = "maintext", verbosity = 3)
my_corpus <- corpus(extracted_texts)
使用未修改的文件进行测试,其中一个文件已知有空字段
输入: 5 个文件,其中包含 4 个 w/o 空或空 text_field
和 1 个空文件 text field
。此外,所有文件都有西欧 (Windows) 1252 编码。
错误:
Reading texts from C:/Users/Nathan/Documents/R/corpus_linguistics/texts_unmodified/*.json
, using glob pattern
... reading (json) file: C:/Users/Nathan/Documents/R/corpus_linguistics/texts_unmodified/border_2014_02_17__1589147645.json
File doesn't contain a single valid JSON object.
contain a single valid JSON object.
... reading (json) file: C:/Users/Nathan/Documents/R/corpus_linguistics/texts_unmodified/border_2014_03_13__1589150325.json
File doesn't contain a single valid JSON object.
Column 14 ['maintext'] of item 1 is length 0. This (and 0 others like it) has been filled with NA (NULL for list columns) to make each item uniform. ... read 5 documents.
结果: 一个由 5 个文档组成的格式正确的语料库。一份文件缺少标记或类型。尽管有错误,但语料库似乎构建正确。可能由于编码问题,某些特殊字符无法正常显示。我无法检查这个。
使用已知没有空字段的已清理文件进行测试
输入文件: 4 个没有空字段或空字段的文件 JSON。在所有情况下,text_field
包含文本并且 title_rss
字段已被删除。每个文件都从西欧 (Windows) 1252 转换为 Unicode UTF-8-65001。
错误:NONE!
结果: 语料库格式正确。
非常感谢两位开发人员提供的详细反馈和有用的线索。非常感谢您的协助。
这里有几种可能性,但最有可能的是:
从 readtext()
的角度来看,您的一个文件的 JSON 结构不正确。即使从严格的 JSON 格式来看这可能没问题,但如果您的文本字段之一为空,那么这将导致错误。 (请参阅下面的演示和解决方案。)
虽然 readtext()
可以采用 "glob" pattern match,但 list.files()
可以采用正则表达式。有可能(但不太可能)您在 list.files(pattern = "*.json"...
中选择了您不想要的东西。但这对于 readtext()
来说不是必需的——见下文。
为了演示,让我们将 data_corpus_inaugural
中的每个文档写成单独的 JSON 文件,然后使用 readtext()
.
读取它们
library("quanteda", warn.conflicts = FALSE)
## Package version: 2.0.1
## Parallel computing: 2 of 8 threads used.
## See https://quanteda.io for tutorials and examples.
tmpdir <- tempdir()
corpdf <- convert(data_corpus_inaugural, to = "data.frame")
for (d in corpdf$doc_id) {
cat(jsonlite::toJSON(dplyr::filter(corpdf, doc_id == d)),
file = paste0(tmpdir, "/", d, ".json")
)
}
head(list.files(tmpdir))
## [1] "1789-Washington.json" "1793-Washington.json" "1797-Adams.json"
## [4] "1801-Jefferson.json" "1805-Jefferson.json" "1809-Madison.json"
要阅读它们,您可以在此处使用 "glob" 模式补丁,只需阅读 JSON 文件。
rt <- readtext::readtext(paste0(tmpdir, "/*.json"),
text_field = "text", docid_field = "doc_id"
)
summary(corpus(rt), n = 5)
## Corpus consisting of 58 documents, showing 5 documents:
##
## Text Types Tokens Sentences Year President FirstName
## 1789-Washington.json 625 1537 23 1789 Washington George
## 1793-Washington.json 96 147 4 1793 Washington George
## 1797-Adams.json 826 2577 37 1797 Adams John
## 1801-Jefferson.json 717 1923 41 1801 Jefferson Thomas
## 1805-Jefferson.json 804 2380 45 1805 Jefferson Thomas
## Party
## none
## none
## Federalist
## Democratic-Republican
## Democratic-Republican
所以一切正常。
但是如果我们添加到这个文本字段为空的文件,则会产生有问题的错误:
cat('[ { "doc_id" : "d1", "text" : "this is a file" },
{ "doc_id" : "d2", "text" : } ]',
file = paste0(tmpdir, "/badfile.json")
)
rt <- readtext::readtext(paste0(tmpdir, "/*.json"),
text_field = "text", docid_field = "doc_id"
)
## File doesn't contain a single valid JSON object.
## Error: This JSON file format is not supported.
是的,那不是有效的 JSON 文件,因为它包含一个没有值的标签。但我怀疑你的一个文件中有类似的东西。
以下是识别问题的方法:遍历 b
(来自问题,而不是我在下面指定的那样)。
b <- tail(list.files(tmpdir, pattern = ".*\.json", full.names = TRUE))
for (f in b) {
cat("Reading:", f, "\n")
rt <- readtext::readtext(f, text_field = "text", docid_field = "doc_id")
}
## Reading: /var/folders/92/64fddl_57nddq_wwqpjnglwn48rjsn/T//RtmpuhmGRK/2001-Bush.json
## Reading: /var/folders/92/64fddl_57nddq_wwqpjnglwn48rjsn/T//RtmpuhmGRK/2005-Bush.json
## Reading: /var/folders/92/64fddl_57nddq_wwqpjnglwn48rjsn/T//RtmpuhmGRK/2009-Obama.json
## Reading: /var/folders/92/64fddl_57nddq_wwqpjnglwn48rjsn/T//RtmpuhmGRK/2013-Obama.json
## Reading: /var/folders/92/64fddl_57nddq_wwqpjnglwn48rjsn/T//RtmpuhmGRK/2017-Trump.json
## Reading: /var/folders/92/64fddl_57nddq_wwqpjnglwn48rjsn/T//RtmpuhmGRK/badfile.json
## File doesn't contain a single valid JSON object.
## Error: This JSON file format is not supported.
我正在尝试使用 readtext
从新闻网站将大量 JSON 文件加载到 quanteda 语料库中。为了简化这个过程,JSON 文件都在工作目录中。但我也在他们自己的目录中尝试过。
- 当使用
c()
创建一个显式定义一小部分文件的变量时,readtext
可以正常工作,并且可以使用corpus()
.[=114= 正确创建语料库] - 当尝试使用
list.files()
创建变量以列出所有 +1500 JSON 文件时readtext
无法按预期工作,出现 return 错误,并且没有创建语料库。
我试图检查两种定义文本集的方法(即 c()
和 list.files()
)以及 paste0()
.
# Load libraries
library(readtext)
library(quanteda)
# Define a set of texts explicitly
a <- c("border_2020_05_10__1589150513.json","border_2020_05_10__1589143358.json","border_2020_05_07__1589170960.json")
# This produces a corpus
extracted_texts <- readtext(a, text_field = "maintext")
my_corpus <- corpus(extracted_texts)
# Define a set of all texts in working directory
b <- list.files(pattern = "*.json", full.names = F)
# This, which I hope to use, produces an error
extracted_texts <- readtext(b, text_field = "maintext")
my_corpus <- corpus(extracted_texts)
extracted_texts <- readtext(b, text_field = "maintext")
产生的错误如下
File doesn't contain a single valid JSON object.
Error: This JSON file format is not supported.
这很令人费解,因为使用 a
调用的相同文件不会产生错误。我 validated several of the JSON files which in every case returned VALID (RFC 8259), the IETF standard 为 JSON.
检查 a
和 b
之间的差异:
typeof()
returns"character"
对于a
和b
.is.vector()
和is.atomic()
returnTRUE
两者。is.list()
returnsFALSE
两个。- 它们在 RStudio 中和在控制台中调用时看起来相似
我真的很困惑为什么 a
有效而 b
无效。
最后,尝试完全模仿 readtext documentation 所采用的程序,还尝试了以下操作:
# XXXX = my username
data_dir <- file.path("C:/Users/XXXX/Documents/R/")
d <- readtext(paste0(data_dir, "/corpus_linguistics/*.json"), text_field = "maintext")
这也return编辑了错误
File doesn't contain a single valid JSON object.
Error: This JSON file format is not supported.
此时我被难住了。提前感谢您对如何前进的任何见解。
解决方案和总结
- 不干净的数据: 一些输入 JSON 文件有空
main_text
字段。这些对分析没有用,应该删除。所有文件都包含一个名为"title_rss"
的 JSON 字段,该字段为空。这可以通过目录级查找和替换为 Notepad ++,或者可能是 R 或 Python 来消除,尽管我仍然缺乏这方面的技能。此外,文件不是 UTF-8 编码,已通过 Codepage Converter. 解决
- 调用目录字符串的方法: readtext How to Use documentation and several third party tutorials中使用了
list.files()
方法。此方法适用于 *.txt 文件,但由于某些原因,它似乎不适用于这些特定的 JSON 文件。一旦 JSON 文件被正确清理和编码,下面的方法就可以正常工作。如果data_dir
包装在list.files()
函数中,则会产生以下错误:Error in list_files(file, ignore_missing, TRUE, verbosity) : File '' does not exist.
我不确定为什么会这样,但是对于这些 JSON 文件,将其保留在外面是有效的。
# Load libraries
library(readtext)
library(quanteda)
# Define a set of texts explicitly
data_dir <- "C:/Users/Nathan/Documents/R/corpus_linguistics/"
extracted_texts <- readtext(paste0(data_dir, "texts_unmodified/*.json"), text_field = "maintext", verbosity = 3)
my_corpus <- corpus(extracted_texts)
使用未修改的文件进行测试,其中一个文件已知有空字段
输入: 5 个文件,其中包含 4 个 w/o 空或空 text_field
和 1 个空文件 text field
。此外,所有文件都有西欧 (Windows) 1252 编码。
错误:
Reading texts from C:/Users/Nathan/Documents/R/corpus_linguistics/texts_unmodified/*.json
, using glob pattern
... reading (json) file: C:/Users/Nathan/Documents/R/corpus_linguistics/texts_unmodified/border_2014_02_17__1589147645.json
File doesn't contain a single valid JSON object.
contain a single valid JSON object.
... reading (json) file: C:/Users/Nathan/Documents/R/corpus_linguistics/texts_unmodified/border_2014_03_13__1589150325.json
File doesn't contain a single valid JSON object.
Column 14 ['maintext'] of item 1 is length 0. This (and 0 others like it) has been filled with NA (NULL for list columns) to make each item uniform. ... read 5 documents.
结果: 一个由 5 个文档组成的格式正确的语料库。一份文件缺少标记或类型。尽管有错误,但语料库似乎构建正确。可能由于编码问题,某些特殊字符无法正常显示。我无法检查这个。
使用已知没有空字段的已清理文件进行测试
输入文件: 4 个没有空字段或空字段的文件 JSON。在所有情况下,text_field
包含文本并且 title_rss
字段已被删除。每个文件都从西欧 (Windows) 1252 转换为 Unicode UTF-8-65001。
错误:NONE!
结果: 语料库格式正确。
非常感谢两位开发人员提供的详细反馈和有用的线索。非常感谢您的协助。
这里有几种可能性,但最有可能的是:
从
readtext()
的角度来看,您的一个文件的 JSON 结构不正确。即使从严格的 JSON 格式来看这可能没问题,但如果您的文本字段之一为空,那么这将导致错误。 (请参阅下面的演示和解决方案。)虽然
readtext()
可以采用 "glob" pattern match,但list.files()
可以采用正则表达式。有可能(但不太可能)您在list.files(pattern = "*.json"...
中选择了您不想要的东西。但这对于readtext()
来说不是必需的——见下文。
为了演示,让我们将 data_corpus_inaugural
中的每个文档写成单独的 JSON 文件,然后使用 readtext()
.
library("quanteda", warn.conflicts = FALSE)
## Package version: 2.0.1
## Parallel computing: 2 of 8 threads used.
## See https://quanteda.io for tutorials and examples.
tmpdir <- tempdir()
corpdf <- convert(data_corpus_inaugural, to = "data.frame")
for (d in corpdf$doc_id) {
cat(jsonlite::toJSON(dplyr::filter(corpdf, doc_id == d)),
file = paste0(tmpdir, "/", d, ".json")
)
}
head(list.files(tmpdir))
## [1] "1789-Washington.json" "1793-Washington.json" "1797-Adams.json"
## [4] "1801-Jefferson.json" "1805-Jefferson.json" "1809-Madison.json"
要阅读它们,您可以在此处使用 "glob" 模式补丁,只需阅读 JSON 文件。
rt <- readtext::readtext(paste0(tmpdir, "/*.json"),
text_field = "text", docid_field = "doc_id"
)
summary(corpus(rt), n = 5)
## Corpus consisting of 58 documents, showing 5 documents:
##
## Text Types Tokens Sentences Year President FirstName
## 1789-Washington.json 625 1537 23 1789 Washington George
## 1793-Washington.json 96 147 4 1793 Washington George
## 1797-Adams.json 826 2577 37 1797 Adams John
## 1801-Jefferson.json 717 1923 41 1801 Jefferson Thomas
## 1805-Jefferson.json 804 2380 45 1805 Jefferson Thomas
## Party
## none
## none
## Federalist
## Democratic-Republican
## Democratic-Republican
所以一切正常。
但是如果我们添加到这个文本字段为空的文件,则会产生有问题的错误:
cat('[ { "doc_id" : "d1", "text" : "this is a file" },
{ "doc_id" : "d2", "text" : } ]',
file = paste0(tmpdir, "/badfile.json")
)
rt <- readtext::readtext(paste0(tmpdir, "/*.json"),
text_field = "text", docid_field = "doc_id"
)
## File doesn't contain a single valid JSON object.
## Error: This JSON file format is not supported.
是的,那不是有效的 JSON 文件,因为它包含一个没有值的标签。但我怀疑你的一个文件中有类似的东西。
以下是识别问题的方法:遍历 b
(来自问题,而不是我在下面指定的那样)。
b <- tail(list.files(tmpdir, pattern = ".*\.json", full.names = TRUE))
for (f in b) {
cat("Reading:", f, "\n")
rt <- readtext::readtext(f, text_field = "text", docid_field = "doc_id")
}
## Reading: /var/folders/92/64fddl_57nddq_wwqpjnglwn48rjsn/T//RtmpuhmGRK/2001-Bush.json
## Reading: /var/folders/92/64fddl_57nddq_wwqpjnglwn48rjsn/T//RtmpuhmGRK/2005-Bush.json
## Reading: /var/folders/92/64fddl_57nddq_wwqpjnglwn48rjsn/T//RtmpuhmGRK/2009-Obama.json
## Reading: /var/folders/92/64fddl_57nddq_wwqpjnglwn48rjsn/T//RtmpuhmGRK/2013-Obama.json
## Reading: /var/folders/92/64fddl_57nddq_wwqpjnglwn48rjsn/T//RtmpuhmGRK/2017-Trump.json
## Reading: /var/folders/92/64fddl_57nddq_wwqpjnglwn48rjsn/T//RtmpuhmGRK/badfile.json
## File doesn't contain a single valid JSON object.
## Error: This JSON file format is not supported.