首页 > 解决方案 > 使用 grepl 在管道中创建 data.table 列

问题描述

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

我在这里这里寻求帮助,似乎有很多关于这个主题的问题,但它似乎并没有直接解决我的问题。

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

据我了解,lapply在 a中使用data.table会将一个函数应用于整个列(即,sum我从另一个发布的问题中发现),但不会在逐行的基础上工作。此外,我可以使用. 所以我会想到其中一个工作。meanna.approxnew_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

标签: rdata.tablegrepl

解决方案


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

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

你可以检查一下,这是一个非常有启发性的链接。

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

推荐阅读