【问题标题】:How to set new column based on multiple conditions in data.table?如何根据data.table中的多个条件设置新列?
【发布时间】:2015-09-18 09:00:49
【问题描述】:

我正在尝试基于文本搜索来收集目录信息。在Text列中搜索某个字符串,并将一些描述放入新列C_Organization

这里是示例数据:

# load packages:
pacman::p_load("data.table",
               "stringr")

# make sample data:
DE <- data.table(c("John", "Sussan", "Bill"),
                 c("Text contains MIT", "some text with Stanford University", "He graduated from Yale"))

colnames(DE) <- c("Name", "Text")

> DE
     Name                               Text
1:   John                  Text contains MIT
2: Sussan some text with Stanford University
3:   Bill             He graduated from Yale

搜索某个字符串并使用新列创建一个新的data.table:

mit <- DE[str_detect(DE$Text, "MIT"), .(Name, C_Organization = "MIT")]
yale <- DE[str_detect(DE$Text, "Yale"), .(Name, C_Organization = "Yale")]
stanford <- DE[str_detect(DE$Text, "Stanford"), .(Name, C_Organization = "Stanford")]

# bind them together:
combine_table <- rbind(mit, yale, stanford)

combine_table

     Name C_Organization
1:   John            MIT
2:   Bill           Yale
3: Sussan       Stanford

这种 pick-and-combine 方法效果很好,但似乎有点乏味。是否可以在data.table中一步完成?

编辑

由于我的数据分析能力差,数据不干净,我需要把问题说清楚:

  1. 真实数据有点复杂:

    (1) 在某些情况下,一个人来自两个以上的组织,例如Jack, UC Berkeley, Bell lab。和

    (2) 同一组织的同一个人出现在不同年份,如Steven, MIT, 2011Steven, MIT, 2014

  2. 我想弄清楚:

    (1) 每个组织有多少人。如果一个人属于多个组织,则将出现最多的组织设为他的组织。 (即按受欢迎程度。)例如,John, MIT, AMS, Bell lab,如果 MIT 出现 30 次,AMS 12 次,Bell lab 26 次。然后将MIT 设为他的组织。

    (2) 计算每年有多少人。这与我最初的问题没有直接关系,但为了以后的计算,我不想扔掉这些记录。

【问题讨论】:

  • 你的意思是你有向量v = c("MIT","Yale","Stanford") 并且你想检索DE 中的所有行在列text 中有这个?
  • 是的。谢谢你的提问。你用更好的方式表达了我的问题。我应该提到这个向量在真实数据集中可能更长。
  • 您的pacman:: 电话会降低问题的重现性。你可以使用sapply(c("pkg1","pkg2"), require)
  • @jangorecki 感谢您让我知道这一点。我一直试图找出如何简洁地写require(pkg1), require(pkg2)...sapply 确实是个好主意,因为它不需要像 pacman 这样的额外包。
  • @Nick,如果每个名字有几个相同的学校,下面的显示是否满足你?

标签: r data.table


【解决方案1】:

另一种解决方案考虑到一个文本中的多个匹配项,按行操作并将匹配项绑定在一起:

uni <- c("MIT","Yale","Stanford")
DE[,idx:=.I][, c_org := paste(uni[str_detect(Text, uni)], collapse=","), idx]

这给出了:

> DE
     Name                                   Text idx             c_org
1:   John                      Text contains MIT   1               MIT
2: Sussan     some text with Stanford University   2          Stanford
3:   Bill He graduated from Yale, MIT, Stanford.   3 MIT,Yale,Stanford
4:   Bill                              some text   4                  

当您在Name 中有相同的名称时,按行操作的优势显而易见。当你这样做时:

DE[, uni[str_detect(Text, uni)], Name]

你得到的结果不正确:

     Name       V1
1:   John      MIT
2: Sussan Stanford
3:   Bill      MIT
4:   Bill Stanford

=> 你不知道第四行是哪个比尔。此外,Yale 不包含在“第一个”账单中(即原始数据集的第 3 行)。


使用过的数据:

DE <- structure(list(Name = c("John", "Sussan", "Bill", "Bill"), Text = c("Text contains MIT", "some text with Stanford University", "He graduated from Yale, MIT, Stanford.", "some text")), .Names = c("Name", "Text"), row.names = c(NA, -4L), class = c("data.table", "data.frame"))

【讨论】:

  • 感谢您的回答。你能解释一下uni[str_detect(Text, uni)] 是如何工作的吗?
  • @Nick 它返回来自uni 向量的值,在Text 列中有匹配项。
  • 所以uni[True, False, True] 返回MIT, Stanford?向量如何接受布尔值并返回其元素?
  • @Nick 你必须使用uni[c(T, F, T)] 来获取这些值。通过将[c(T, F, T)] 添加到uni,您可以为uni 提供一个索引,该索引应该保留哪些值。在这种情况下,第一个和最后一个。
猜你喜欢
  • 2019-07-24
  • 1970-01-01
  • 1970-01-01
  • 2022-11-22
  • 1970-01-01
  • 2023-01-13
  • 2019-11-22
  • 2020-07-11
  • 1970-01-01
相关资源
最近更新 更多