【问题标题】:Split parts of strings into a list column and then make a vector column将部分字符串拆分为列表列,然后制作一个向量列
【发布时间】:2013-10-04 04:46:43
【问题描述】:

我正在尝试在满足特定条件的每一行上运行一个函数,该函数返回一个数据框 - 然后将数据框列表和 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 代码行作为变量名等。

【问题讨论】:

  • 能否提供db的样本数据?顺便说一句,您在getUrls(text 中缺少)。此外,使用 TRUE 和 FALSE(而不是 T 和 F)被认为更安全。
  • 感谢鼓励,见下文,欢迎提供更多反馈。

标签: r data.table


【解决方案1】:

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

【讨论】:

  • 我觉得像例子,也许这个答案的其他部分属于问题......?
  • 这是我第一次尝试回答我自己的问题......现在问题中的信息实际上是我问它时(在邮件列表上)得到的信息......我可以尝试重新调整以使其更具教学性,但“创作”问题和答案似乎有点人为。我想我会暂时离开它,希望它对某些人有用。
  • 是的,我以前也从未回答过我自己的问题,但我认为这样做的唯一原因是出于教学目的,对吧?无论如何,它也很好,就像我在邮件列表上看到的一样:)。
  • 我在尝试使用 := 时遇到错误。它来自哪里?
猜你喜欢
  • 1970-01-01
  • 2014-09-27
  • 2021-07-17
  • 2021-12-02
  • 1970-01-01
  • 2018-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多