Найти все пересекающиеся векторы в списке векторов в R - PullRequest
0 голосов
/ 28 сентября 2019

У меня есть список векторов sets следующим образом.

sets <- list(b = c("b4", "b5", "b6"),
             c = c("c2", "c3", "b4", "b5", "c6"),
             d = c("d1", "d2"),
             e = c("e45", "e55", "e65"),
             f = c("f4", "f5", "d1", "f6"),
             g = c("g1", "g2"),
             h = c("h5", "h6", "h7"),
             i = c("i9", "h5", "g1", "h6", "i8", "i7"),
             j = c("j1", "j2", "j3"))

Я хочу идентифицировать все элементы этого списка, которые являются уникальными, а также все элементы, которые перекрываются / пересекаются.

Как это сделать в R?

unique <- list(e = c("e45", "e55", "e65"),
               j = c("j1", "j2", "j3"))

intersects <- list(d = c("d1", "d2"),
                   b = c("b4", "b5", "b6"),
                   c = c("c2", "c3", "b4", "b5", "c6"),
                   f = c("f4", "f5", "d1", "f6"),
                   g = c("g1", "g2"),
                   h = c("h5", "h6", "h7"),
                   i = c("i9", "h5", "g1", "h6", "i8", "i7"))

Ответы [ 3 ]

1 голос
/ 28 сентября 2019

Учитывая, что элементы списка должны быть разделены в соответствии с:

  • Элементы списка с пустыми пересечениями по всем остальным компонентам списка,
  • Элементы списка с непустым пересечением по отношению кнекоторый другой компонент списка,

способ достижения этого в базе R заключается в следующем:

## find set components w/ empty intersections w/ all other components
isUnique <- sapply(seq_along(sets), function(i) length(intersect(sets[[i]], unlist(sets[-i]))) < 1)

## empty intersect components
sets[isUnique]
#> $e
#> [1] "e45" "e55" "e65"
#> 
#> $j
#> [1] "j1" "j2" "j3"

## non-empty intersect components 
sets[!isUnique]
#> $b
#> [1] "b4" "b5" "b6"
#> 
#> $c
#> [1] "c2" "c3" "b4" "b5" "c6"
#> 
#> $d
#> [1] "d1" "d2"
#> 
#> $f
#> [1] "f4" "f5" "d1" "f6"
#> 
#> $g
#> [1] "g1" "g2"
#> 
#> $h
#> [1] "h5" "h6" "h7"
#> 
#> $i
#> [1] "i9" "h5" "g1" "h6" "i8" "i7"
0 голосов
/ 28 сентября 2019

Значения пересечения

Для значений пересечения есть одна встроенная функция в R, которая может выполнить работу.intersect делает именно этот пример:

intersect(c("b4", "b5", "b6"),c("c2", "c3", "b4", "b5", "c6"))
# [1] "b4" "b5"

Однако, если вы хотите применить его с несколькими значениями, вам нужно использовать другую встроенную функцию с именем Reduce пример:

sets <- list(b = c("b4", "b5", "b6"),
         c = c("c2", "c3", "b4", "b5", "c6"),
         d = c("d1", "d2"),
         e = c("e45", "e55", "e65"),
         f = c("f4", "f5", "d1", "f6"),
         g = c("g1", "g2"),
         h = c("h5", "h6", "h7"),
         i = c("i9", "h5", "g1", "h6", "i8", "i7"),
         j = c("j1", "j2", "j3"))

Reduce(intersect,sets)

источник

Уникальные значения в списке

Вы можете использовать функцию do.call, для этого примера это будет:

unique(do.call("c",sets))
# [1] "b4"  "b5"  "b6"  "c2"  "c3"  "c6" ....

Надеюсь, что это может помочь

0 голосов
/ 28 сентября 2019

Вот моя попытка получить список пересечений:

sets <- list(b = c("b4", "b5", "b6"),
             c = c("c2", "c3", "b4", "b5", "c6"),
             d = c("d1", "d2"),
             e = c("e45", "e55", "e65"),
             f = c("f4", "f5", "d1", "f6"),
             g = c("g1", "g2"),
             h = c("h5", "h6", "h7"),
             i = c("i9", "h5", "g1", "h6", "i8", "i7"),
             j = c("j1", "j2", "j3"))

set.names <- names(sets)
names(set.names) <- set.names

sets.intersect <- lapply(set.names, function(x) {
  res <- lapply(set.names, function(y) {
    if (x != y) {
      intersect(sets[[x]], sets[[y]])
    }
    else (
      character(0)
    )
  })
  Filter(function(x) length(x) > 0, res)
})

output.intersect <- lapply(sets.intersect, function(x) {
  res <- unlist(unname(x))
})
output.intersect <- Filter(function(x) !is.null(x), output.intersect)

# RESULT
dput(output.intersect)
structure(
  list(
    b = c("b4", "b5"), 
    c = c("b4", "b5"), 
    d = "d1", 
    f = "d1", 
    g = "g1", 
    h = c("h5", "h6"), 
    i = c("g1", "h5", "h6")
  ), .Names = c("b", "c", "d", "f", "g", "h", "i")
 )

Я пытался сделать это без циклов for, что требует некоторых приемов со списком и именами векторов.

...