通过在数据表的两列之间使用%like%进行过滤

时间:2017-12-11 14:23:46

标签: r data.table

Hello stackoverflowers,

我想知道是否可以在同一数据表的两列之间的数据表中逐行使用%like%运算符。

以下可重复的示例将使其更加清晰。

首先准备数据

library(data.table)

iris <- as.data.table(iris)
iris <- iris[seq.int(from = 1, to = 150,length.out = 5)]
iris[, Species2 := c('set', "set|vers", "setosa", "nothing" , "virginica")]

因此数据集如下所示。

   Sepal.Length Sepal.Width Petal.Length Petal.Width    Species  Species2
1:          5.1         3.5          1.4         0.2     setosa       set
2:          4.9         3.6          1.4         0.1     setosa  set|vers
3:          6.4         2.9          4.3         1.3 versicolor    setosa
4:          6.4         2.7          5.3         1.9  virginica   nothing
5:          5.9         3.0          5.1         1.8  virginica virginica

我想按行使用以下命令。

iris[Species%like%Species2]

但它不明白我想要它排。那可能吗? 结果应该是1,2,5行。

4 个答案:

答案 0 :(得分:2)

一种方法是逐行分组:

doAnswer(i -> {
  ((Runnable) i.getArguments()[0]).run();
  return null;
}).when(executor).execute(any());

或者根据@docendodiscimus的评论,如果有重复的条目,你可以这样做:

iris[, .SD[Species %like% Species2], by = 1:5]
#   : Sepal.Length Sepal.Width Petal.Length Petal.Width   Species  Species2
#1: 1          5.1         3.5          1.4         0.2    setosa       set
#2: 2          4.9         3.6          1.4         0.1    setosa  set|vers
#3: 5          5.9         3.0          5.1         1.8 virginica virginica

答案 1 :(得分:2)

您无法将矢量传递给pattern的{​​{1}}参数,因为它会调用%like%并且这些参数不会被矢量化。您可以使用grepl/grep为每行调用mapply来获得您想要的内容:

%like%

Microbenchmark主要是出于我自己的好奇心,但感兴趣的是其他任何人:

iris[mapply(function(x,y) x %like% y, Species, Species2) ]

#   Sepal.Length Sepal.Width Petal.Length Petal.Width   Species  Species2
#1:          5.1         3.5          1.4         0.2    setosa       set
#2:          4.9         3.6          1.4         0.1    setosa  set|vers
#3:          5.9         3.0          5.1         1.8 virginica virginica

由于set.seed(1) dt <- data.table(Species = replicate(100000, paste0(sample(LETTERS, 6), collapse = "")), Species2 = replicate(100000, paste0(sample(LETTERS, 3), collapse = ""))) microbenchmark::microbenchmark( mapply = dt[mapply(function(x,y) x %like% y, Species, Species2) ], by_group1 = dt[, .SD[Species[1L] %like% Species2[1L]], by = .(Species, Species2)], by_group2 = dt[, .SD[Species %like% Species2], by = 1:nrow(dt)], str_detect = dt[stri_detect_regex(Species, Species2)], by_species2 = dt[,.SD[Species %like% Species2], by = Species2], by_species2I = dt[dt[, .I[Species %like% Species2], by = Species2]$V1], times = 5) Unit: milliseconds expr min lq mean median uq max neval mapply 669.9691 680.2241 700.3758 685.8262 715.8373 750.0224 5 by_group1 10906.2179 10908.0985 10951.5651 10914.7002 11009.0683 11019.7408 5 by_group2 16738.4390 16826.4793 16907.8428 16902.9490 16970.6143 17100.7324 5 str_detect 430.7768 431.1002 432.2279 431.9284 433.3488 433.9855 5 by_species2 2482.7583 2518.6858 2547.5882 2531.4913 2599.0159 2605.9899 5 by_species2I 110.1486 114.6775 115.9223 117.5270 118.5033 118.7553 5 操作非常慢,因此只运行了5次。使用by_group*的@ eddi方法看起来最快(假设我的方法正确无误)。

另外,使用较少的组重新运行基准测试,在这种情况下似乎.I仍然是最快的,而另一个by_species2I仍然是最慢的(从#开始有意义) by_group*的群组总是数据大小,而by_group2的群组将接近数据大小。

by_group1

答案 2 :(得分:2)

${DC_CURRENCY_SELECTOR_VERIFY} = Encode String To Bytes ${DC_CURRENCY_SELECTOR_VERIFY} ASCII errors=ignore 只是%like%的包装,因此模式(右侧)只能是长度1.您应该看到有关此的警告。

grepl包允许您对stringi参数进行矢量化。

pattern

如果你喜欢操作员风格而不是功能,你可以自己制作:

library(stringi)

iris[stri_detect_regex(Species, Species2)]

答案 3 :(得分:2)

各种答案都有正确的点点滴滴 - 按Species2

进行
iris[, .SD[Species %like% Species2], by = Species2]

如果这很慢 - use .I instead