我有一个tibble:
df <- tibble(x = c('a', 'ab', 'abc', 'abcd', 'abd', 'efg'))
我想删除作为其他行的子字符串的行,结果是:
result <- tibble(x = c('abcd', 'abd', 'efg'))
该解决方案必须非常有效,因为大约有1M行文本。
str_extract(df$x, "foo") == "foo"
用于测试;foo";是CCD_ 2中任何元素的子串。它将始终至少为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
创建于2022-02-18由reprex包(v2.0.0(
在小型数据集上,速度较慢(在这些情况下,速度不是问题(,但在较大的数据集上速度较快。速度取决于与数据大小相比有多少个唯一组。
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)]]