我正在尝试在满足某个标准的每一行上运行一个函数,该标准返回一个数据框 - 然后我们想要获取数据框列表并将它们重新组合在一起以获得完全独立的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代码行作为变量名等。
答案 0 :(得分: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行,url有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
(感谢Matthew Dowle和Ricardo Saporta关于data.table-help邮件列表)