我们可以重写它,使它更紧凑,避开函数。我们将分两步完成,首先我们将创建一个包含列表的新列(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)