无法使用 tm for R 中的 DataframeSource 从数据框中获取元数据

Can't get metadata from dataframe using DataframeSource in tm for R

我有一个包含以下变量的数据框:

doc_id  text  URL  author  date  forum 

当我运行

samplecorpus <- Corpus(DataframeSource(sampledataframe))

文档说我应该得到一个语料库,其中包含作为文档级元数据添加的所有额外变量。 https://rdrr.io/rforge/tm/man/DataframeSource.html http://finzi.psych.upenn.edu/R/library/tm/html/DataframeSource.html

相反,我得到了一个语料库,其中包含所有按正确顺序排列的正确文档,但它们的所有元数据都是空白的。我需要此元数据来过滤文档以供将来分析。

其他人也问过类似的问题,但一直没有人回答... In tm version a readTabular() replacement tm package DataframeSource () ignores my other columns as metadata

有人知道如何解决这个问题吗?

谢谢!

tm 的文档对此进行了解释(请参阅 ??tm::DublicCore)。来自文档:

A corpus has two types of metadata. Corpus metadata ("corpus") contains corpus specific metadata in form of tag-value pairs. Document level metadata ("indexed") contains document specific metadata but is stored in the corpus as a data frame. Document level metadata is typically used for semantic reasons (e.g., classifications of documents form an own entity due to some high-level information like the range of possible values) or for performance reasons (single access instead of extracting metadata of each document). The latter can be seen as a from of indexing, hence the name "indexed". Document metadata ("local") are tag-value pairs directly stored locally at the individual documents.

DataframeSource 仅自动分配 语料库 元数据*。例如,查看以下打印内容:

library(tm)
data <- data.frame(doc_id = c(234345345, 1299),
                   text = c("The Prince and the Pauper", 
                            "Little Women"),
                   author = c('Mark Twain', 'Louisa May Alcott'),
                   date = c(1881, 1868),
                   stringsAsFactors = FALSE)

samplecorpus <- Corpus(DataframeSource(data))
meta(samplecorpus) 
# Or even
meta(samplecorpus[1], tag = 'author')

为了在文档级别分配元数据,您可以使用 meta 更改标签。奇怪的是,这仅在您使用 VCorpus 时有效。所以稍微改变上面的内容,你可以这样做:

samplecorpus <- VCorpus(DataframeSource(data))
# Can now set document metadata tags
meta(samplecorpus[[1]], tag = 'author') <- 'Mark Twain'

*编辑:

进一步考虑(并回应 OP 的评论),我同意该文档不是对包观察到的行为的完全准确描述。上面引用的文档指的是三个级别(语料库、索引文档级别和本地文档级别),在我的示例中,它们分别对应于 samplecorpussamplecorpus[1]samplecorpus[[1]]。如果这是正确的,那么元数据 DataframeSource 在承诺的级别分配(如果有点含糊,因为他们从未指定 which文件级)。然而,文档还声称索引文档级别存储为数据框,本地存储为标签值对,但两者都存储为列表。令人困惑。我只能得出结论,这是包实现中的错误或文档中的错误。

除非联系软件包作者来解决这个问题(这不是一个坏主意),否则我会提出以下解决方法:

samplecorpus <- VCorpus(DataframeSource(data))
transfer_metadata <- function(x, i, tag){
  return(meta(x[i], tag=tag)[[tag]])
}

tags <- colnames(data)
tags <- tags[! tags %in% c('doc_id', 'text')]

for(i in 1:length(samplecorpus)){
  for (tag in tags){
    meta(samplecorpus[[i]], tag=tag) <- transfer_metadata(samplecorpus, i=i, tag=tag)
    }
}

您必须检查所有内容是否正确加载。我制作了一个示例文档 data.frame 以便您了解它是如何工作的。我使用了与您相同的列名并添加了 1 个额外的(标签)。基于这个例子,你可能会检查你是否在某处有问题。

docs <- data.frame(doc_id = c("doc_1", "doc_2"),
                   text = c("This is a text.", "This another one."),
                   url = c("",
                           ""), 
                   author = c("Emi", "Emi"),
                   date = as.Date(c("2018-09-20", "2018-09-21")),
                   forum = c("Whosebug", "Whosebug"),
                   tags = c("r", "tm"),
                   stringsAsFactors = T)

# use Corpus or VCorpus
my_corpus <- Corpus(DataframeSource(docs))
meta(my_corpus)

    url author       date
1     Emi 2018-09-20
2     Emi 2018-09-21
          forum tags
1 Whosebug    r
2 Whosebug   tm

my_index <- meta(my_corpus, "tags") == "r"

inspect(my_corpus[my_index])
<<SimpleCorpus>>
Metadata:  corpus specific: 1, document level (indexed): 5
Content:  documents: 1

          doc_1 
This is a text. 

现在请注意元数据的处理方式有所不同。如果您这样做 str(my_corpus),您将看到以下内容:

List of 2
 $ doc_1:List of 2
  ..$ content: chr "This is a text."
  ..$ meta   :List of 7
  .. ..$ author       : chr(0) 
  .. ..$ datetimestamp: POSIXlt[1:1], format: "2018-09-21 08:55:44"
  .. ..$ description  : chr(0) 
  .. ..$ heading      : chr(0) 
  .. ..$ id           : chr "doc_1"
  .. ..$ language     : chr "en"
  .. ..$ origin       : chr(0) 
  .. ..- attr(*, "class")= chr "TextDocumentMeta"
  ..- attr(*, "class")= chr [1:2] "PlainTextDocument" "TextDocument"
 $ doc_2:List of 2
......

您在此处看到的元信息来自 meta(my_corpus, type = "local")。使用DataframeSource加载的元数据是索引类型,meta(my_corpus, type = "indexed")

the vignette 的第 5 页对于阅读和试验以查看 meta 和 DublinCore 的所有不同选项很重要。