2

我正在尝试在满足特定标准的每一行上运行一个函数,该函数返回一个数据框 - 然后将数据框列表和 rbindlist 放在一起以获得完全独立的 data.table。(我从每个论坛帖子中提取几个 URL 链接,并用它们来自的论坛帖子标记它们)。

我尝试使用 data.table 执行此操作

getUrls <- function(text, id) {
  matches <- str_match_all(text, url_pattern)
  a <- data.frame(urls=unlist(matches))
  a$id <- id
  a
}

a <- db[has_url == TRUE, getUrls(text)]

并得到消息

Error in `$<-.data.frame`(`*tmp*`, "id", value = c(1L, 6L, 1L, 2L, 4L,  : 
  replacement has 11007 rows, data has 29787 

因为有些行有几个 URL...但是,我不在乎这些行长度不匹配,我仍然想要这些行 :) 我认为 J 会让我在行的上下文中执行任意 R 代码作为变量名称等

4

1 回答 1

3

我们可以重写它,使它更紧凑,避开函数。我们将分两步完成,首先我们将创建一个包含列表的新列(data.table 列几乎可以包含任何内容,甚至是嵌入的 data.tables),然后我们会将它们提取到新数据中。桌子。

url_pattern <- "http[^([:blank:]|\\\"|<|&|#\n\r)]+"

db[(has_url), urls := str_match_all(text, url_pattern)]
urls <- db[(has_url), list(url=unlist(urls)), by=id]

请注意,我们使用 (has_url) 而不是 has_url == T,这使用了更快的二进制索引(尽管在这种情况下,大部分时间都被 str_match_all 占用,因此不会有太大区别)。确保你使用 () ,否则它将不起作用。

第二行创建 db$urls,它是一个 url 列表。第三行生成一个新的 data.table,每个 URL 都有一个条目,ID 字段将它链接回它来自的论坛帖子。

db 有 146k 行,db[(has_url),] 有 11k 行,urls 有 30k 行(有些帖子有多个 url)。

来自 head(urls) 的示例输出:

id  url
14  http://reganmian.net/blog
44  http://vg.no
59  http://koran.co.id

更新,简单的可重现示例

我们先生成一些数据

texts = c("Stian fruit:apple, fruit:banana and fruit:pear",
          "Peter fruit:apple",
          "fruit:banana is delicious",
          "I don't agree")
DT <- data.table(text = texts, id=1:length(texts))

DT
                                             text id
1: Stian fruit:apple, fruit:banana and fruit:pear  1
2:                              Peter fruit:apple  2
3:                      fruit:banana is delicious  3
4:                                  I don't agree  4

我们想从文本列中获取所有“水果”(每一行可能有一个、几个或没有水果)。我们首先使用 str_match_all 将单个水果的列表放入一个新列中。

pattern <- "fruit:\\S*"

DT[, fruit_list := str_match_all(text, pattern)]

现在果园是这样的:

> DT[1]$fruit_list
[[1]]
     [,1]          
[1,] "fruit:apple,"
[2,] "fruit:banana"
[3,] "fruit:pear"  

现在我们想将水果提取到一个新表中,每个水果一行,保持链接回到 ID

fruits <- DT[, list(fruit=unlist(fruit_list)), by=id]

结果

> fruits
   id        fruit
1:  1 fruit:apple,
2:  1 fruit:banana
3:  1   fruit:pear
4:  2  fruit:apple
5:  3 fruit:banana

(感谢 data.table-help 邮件列表上的 Matthew Dowle 和 Ricardo Saporta)

于 2013-09-27T19:10:54.833 回答