从 tibble 中删除子字符串行

Remove substring rows from tibble

我有一个问题:

df <- tibble(x = c('a', 'ab', 'abc', 'abcd', 'abd', 'efg'))

我想删除作为其他行的子字符串的行,导致:

result <- tibble(x = c('abcd', 'abd', 'efg'))

该解决方案必须非常有效,因为有约 100 万行文本。

str_extract(df$x, "foo") == "foo"是为了测试“foo”是否是df$x中任意元素的子串。它始终至少为 1,因为 x 始终是其自身的子串。如果这个数字更高,它也是另一个元素的子串,所以我们需要使用 filter(!).

删除它们
library(tidyverse)

df <- tibble(x = c('a', 'ab', 'abc', 'abcd', 'abd', 'efg'))

df %>% filter(! (x %>% map_lgl(~ sum(str_extract(df$x, .x) == .x, na.rm = TRUE) > 1)))
#> # A tibble: 3 x 1
#>   x    
#>   <chr>
#> 1 abcd 
#> 2 abd  
#> 3 efg

reprex package (v2.0.0)

于 2022-02-18 创建

在小数据集上速度较慢(在那些情况下速度不是问题)但在更大的数据集上速度更快。速度取决于与数据大小相比有多少唯一组。

df <- arrange(df, desc(nchar(x)))
my_strings <- df$x
i <- 1
while(i < length(my_strings)){
  
  indices <- which(str_detect(my_strings[[i]], my_strings[(i+1):length(my_strings)])) + i
  if(length(indices) > 0) my_strings <- my_strings[-indices]
  i <- i + 1
}

可能的改进但未测试:

setDT(df)
indices_df <- df[, .(indices = list(.I)), by = x][order(-nchar(x))]
my_strings <- indices_df$x
i <- 1
while(i < length(my_strings)){

  indices <- which(str_detect(my_strings[[i]], my_strings[(i+1):length(my_strings)])) + i
  if(length(indices) > 0) my_strings <- my_strings[-indices]
  i <- i + 1
}

df[indices_df[x %in% my_strings, unlist(indices)]]