使用grepl在管道中创建data.table列

时间:2018-10-04 00:49:35

标签: r data.table grepl

我正在寻找一种使用data.table在管道序列中创建新的grepl列的方法,以查找出现的特定字符串。

我已经向herehere寻求帮助,围绕该主题似乎有很多疑问,但似乎并不能直接解决我的问题。

此外,我可能对data.table语法有误解,并且正在引用Reference semantics vignettes。我在下面的代码中有两种方法可以通过管道/链式连接,但似乎不起作用。显式创建data.table列的最后一个选项似乎可行,但我想知道是否可以链接/管道化。

据我了解,在lapply中使用data.table会将函数应用于整个列(即,我发现的summeanna.approx从另一个已发布的问题中删除),但无法逐行使用。另外,我可以使用new_col := function(x)将函数应用于给定列中的每一行。因此,我本以为其中一种会起作用。

我(仅在某种程度上)知道grepl期望一个值,但是正在提供向量,并且不确定如何解决这个问题。

感谢您的帮助。

> library(data.table)
> 
> a = c("housefly",
+       "house fly",
+       "HOUSEFLY",
+       "HOUSE FLY")
> 
> dt = data.table(insect = c("housefly",
+                            "house fly",
+                            "HOUSEFLY",
+                            "HOUSE FLY",
+                            "dragonfly",
+                            "dragon fly"))
> 
> # does not work but I could put this in chain/pipe
> dt[, fly_check := sapply(.SD, grepl, paste(a, collapse = "|")), .SDcols = "insect"]
Warning message:
In FUN(X[[i]], ...) :
  argument 'pattern' has length > 1 and only the first element will be used
> dt
       insect fly_check
1:   housefly      TRUE
2:  house fly      TRUE
3:   HOUSEFLY      TRUE
4:  HOUSE FLY      TRUE
5:  dragonfly      TRUE
6: dragon fly      TRUE
> 
> # does not work but I could put this in chain/pipe
> dt[, fly_check := ifelse(grepl(insect, paste(a, collapse = "|")), TRUE, FALSE)]
Warning message:
In grepl(insect, paste(a, collapse = "|")) :
  argument 'pattern' has length > 1 and only the first element will be used
> dt
       insect fly_check
1:   housefly      TRUE
2:  house fly      TRUE
3:   HOUSEFLY      TRUE
4:  HOUSE FLY      TRUE
5:  dragonfly      TRUE
6: dragon fly      TRUE
> 
> # works but can't be chained/piped
> dt$fly_check = sapply(dt$insect, grepl, pattern = paste(a, collapse = "|"))
> dt
       insect fly_check
1:   housefly      TRUE
2:  house fly      TRUE
3:   HOUSEFLY      TRUE
4:  HOUSE FLY      TRUE
5:  dragonfly     FALSE
6: dragon fly     FALSE

2 个答案:

答案 0 :(得分:3)

似乎您正在寻找它,尽管@ chinsoon12(在注释中)给出了一个更简单的解决方案,该解决方案只是直接传递列名:

逻辑:在data.table中,如果您使用.SD参数调用它,则意味着数据的子集,这也表明该列不是作为矢量而是作为data.table对象传递的(因此,您必须使用Vectorize或其他方法操作),另一方面,如果直接将其作为列传递,则grepl在处理类似矢量的结构上不会有问题(@ Chinsoon12解决方案)。

您可以检查this,它是一个非常有启发性的链接。

Exclude

导致:

dt[, fly_check := (Vectorize(grepl)(paste0(a, collapse = "|"),.SD)), .SDcols = c("insect")]

答案 1 :(得分:2)

我认为这只是将%in%应用于a值的简单应用

dt[ , fly_check := insect %in% a]

这似乎比将grepl应用于折叠的a值作为模式更简单。

dt[ , fly_check := grepl( paste0(a, collapse="|") , insect)]

> dt
       insect fly_check
1:   housefly      TRUE
2:  house fly      TRUE
3:   HOUSEFLY      TRUE
4:  HOUSE FLY      TRUE
5:  dragonfly     FALSE
6: dragon fly     FALSE

我想如果您对grepl或'perl'或'fixed'参数提供的必要工具有普遍性,您仍然可以选择ignore.case=TRUE策略。