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

create data.table column in pipe with grepl

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

我已经 and 寻求帮助,围绕这个主题似乎有很多问题,但似乎并没有直接解决我的问题。

此外,我可能误解了 data.table 语法并引用了 Reference semantics vignettes。我有下面的代码,其中有两种方法可能是 piped/chained 但似乎不起作用。明确创建 data.table 列的最后一个选项似乎有效,但我想知道它是否可以 chained/piped.

据我了解,在 data.table 中使用 lapply 会将函数应用于整个列(即 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

看起来你正在寻找这个,尽管@chinsoon12(在评论中)给出了一个更简单的解决方案,它只是直接传递列名:

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

您可以查看 this,它很有启发性 link。

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

这导致:

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

我认为这只是 %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

我想如果您通过 ignore.case=TRUE 获得了通用性或需要 'perl' 或 'fixed' 参数提供的便利,我想您可能仍会选择 grepl 策略。