Удалить дубликат пары в строке - PullRequest
0 голосов
/ 29 мая 2018

В строковой переменной я хотел бы удалить обе части дубликатов;так что я выбираю только уникальные строки.То есть:

У меня есть строка

MyString <- c("aaa", "bbb", "ccc", "ddd", "aaa", "ddd") 

Я хотел бы удалить обе пары дубликатов;и таким образом выберите:

[1] "bbb" "ccc"

Не повезло, я попытался:

 unique((MyString)

Ответы [ 2 ]

0 голосов
/ 29 мая 2018

Найдите набор дубликатов

dups = MyString[ duplicated(MyString) ]

и отбросьте все вхождения в наборе

MyString[ !MyString %in% dups ]

Альтернатива:

setdiff(MyString, dups)

Основанное на таблице решение из@Moody_Mudskipper обеспечивает большую гибкость, например, для выбора строк, которые встречаются дважды.Альтернативно (возможно, быстрее, чем аналогичные table() -разрешения, когда длина MyString длинная), но создать индекс для уникальных строк, найти число совпадений каждой уникальной строки (tabulate() == 1) и использовать их дляподмножество уникальных строк:

UString = unique(MyString)
UString[ tabulate(match(MyString, UString)) == 1 ]

или сохраните необходимость создания UString

MyString[ which(tabulate(match(MyString, MyString)) == 1) ]

Альтернатива: сортировка и затем поиск прогонов длиной 1.

r = rle(sort(MyString))
r$values[ r$lengths == 1 ]

Для производительности, вот некоторые функции, реализующие различные решения

f0 = function(x) x[ !x %in% x[duplicated(x)] ]
f1 = function(x) setdiff( x, x[duplicated(x)] )
f2 = function(x) { ux = unique(x); ux[ tabulate(match(x, ux)) == 1 ] }
f3 = function(x) x[ which( tabulate( match(x, x) ) == 1 ) ]
f4 = function(x) { r = rle(sort(x)); r$values[ r$lengths == 1] }
f5 = function(x) { x = table(x); names(x)[x==1] }
f6 = function(x) x[ !duplicated(x) & !duplicated(x, fromLast = TRUE) ]

, свидетельствующие о том, что они дают идентичные результаты

> identical(f0(x), f1(x))
[1] TRUE
> identical(f0(x), f2(x))
[1] TRUE
> identical(f0(x), f3(x))
[1] TRUE
> identical(f0(x), f4(x))
[1] TRUE
> identical(f0(x), f5(x))
[1] TRUE
> identical(f0(x), f6(x))
[1] TRUE

f5() (также в исходной реализации) не удается для x = character(0)

> f1(character(0))
character(0)
> f5(character(0))
NULL

f4() и f5() возвращают значения в алфавитном порядке, в то время как остальные сохраняют порядок на входе, например unique().Все методы, кроме f5(), работают с векторами другого типа, например, integer() (f5() всегда возвращает символьный вектор, другие возвращают вектор того же типа, что и входные данные).f4() и f5() не распознают уникальные вхождения NA.

и время:

> microbenchmark(f0(x), f1(x), f2(x), f3(x), f4(x), f5(x), f6(x))
Unit: microseconds
  expr     min       lq      mean   median       uq      max neval
 f0(x)   9.195  10.9730  12.35724  11.8120  13.0580   29.100   100
 f1(x)  20.471  22.6625  50.15586  24.6750  25.9915 2600.307   100
 f2(x)  13.708  15.2265  58.58714  16.8180  18.4685 4180.829   100
 f3(x)   7.533   8.8775  52.43730   9.9855  11.0060 4252.063   100
 f4(x)  74.333  79.4305 124.26233  83.1505  87.4455 4091.371   100
 f5(x) 147.744 154.3080 196.05684 158.4880 163.6625 3721.522   100
 f6(x)  12.458  14.2335  58.11869  15.4805  17.0440 4250.500   100

Вот производительность с 10 000 уникальных слов

> x = readLines("/usr/share/dict/words", 10000)
> microbenchmark(f0(x), f1(x), f2(x), f3(x), f4(x), f5(x), f6(x), times = 10)
Unit: microseconds
  expr       min        lq       mean    median        uq       max neval
 f0(x)   848.086   871.359   880.8841   873.637   899.669   916.528    10
 f1(x)  1440.904  1460.704  1556.7154  1589.405  1607.048  1640.347    10
 f2(x)  2143.997  2257.041  2288.1878  2288.329  2334.494  2372.639    10
 f3(x)  1420.144  1548.055  1547.8093  1562.927  1596.574  1601.176    10
 f4(x) 11829.680 12141.870 12369.5407 12311.334 12716.806 12952.950    10
 f5(x) 15796.546 15833.650 16176.2654 15858.629 15913.465 18604.658    10
 f6(x)  1219.036  1356.807  1354.3578  1363.276  1372.831  1407.077    10

И с существенным дублированием

> x = sample(head(x, 1000), 10000, TRUE)
> microbenchmark(f0(x), f1(x), f2(x), f3(x), f4(x), f5(x), f6(x))
Unit: milliseconds
  expr       min        lq      mean    median        uq       max neval
 f0(x)  1.914699  1.922925  1.992511  1.945807  2.030469  2.246022   100
 f1(x)  1.888959  1.909469  2.097532  1.948002  2.031083  5.310342   100
 f2(x)  1.396825  1.404801  1.447235  1.420777  1.479277  1.820402   100
 f3(x)  1.248126  1.257283  1.295493  1.285652  1.329139  1.427220   100
 f4(x) 24.075280 24.298454 24.562576 24.459281 24.700579 25.752481   100
 f5(x)  4.044137  4.120369  4.307893  4.174639  4.283030  7.740830   100
 f6(x)  1.221024  1.227792  1.264572  1.243201  1.295888  1.462007   100

f0() кажется победителем скорости, когда дубликаты редки

> x = readLines("/usr/share/dict/words", 100000)
> microbenchmark(f0(x), f1(x), f3(x), f6(x))
Unit: milliseconds
  expr      min       lq     mean   median       uq      max neval
 f0(x) 11.03298 11.17124 12.17688 11.36114 11.62769 19.83124   100
 f1(x) 21.16154 21.33792 22.76237 21.67234 22.26473 31.99544   100
 f3(x) 21.15801 21.49355 22.60749 21.77821 22.54203 31.17288   100
 f6(x) 18.72260 18.97623 20.29060 19.46875 19.94892 28.17551   100

f3() и f6() выглядят правильно и быстро;f6(), вероятно, легче понять (но обрабатывает только особый случай сохранения слов, которые встречаются ровно один раз).

0 голосов
/ 29 мая 2018
x <- table(MyString)
names(x[x==1])
[1] "bbb" "ccc"

также:

MyString[ !duplicated(MyString) & !duplicated(MyString,fromLast = T) ]
[1] "bbb" "ccc"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...