Как идентифицировать и подсчитать элементы пересечения в R - PullRequest
3 голосов
/ 26 сентября 2019

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

dat <- data.frame(BLUE = c(1, 2, 3, 4, 6, NA),
                  RED = c(2, 3, 6, 7, 9, 13),
                  GREEN = c(4, 6, 8, 9, 10, 11))

или для наглядности:

BLUE  RED  GREEN
1     2    4
2     3    6
3     6    8
4     7    9
6     9    10
NA    13   11

Мне нужно идентифицировать и подсчитать индивидуальное и межгрупповое членство(т.е. сколько идентификаторов было только красным, сколько было красного и синего и т. д.) Мой желаемый результат ниже.Обратите внимание, что столбец идентификаторов просто для справки, этот столбец не будет в ожидаемом выводе.

COLOR                TOTAL  IDs (reference only, not needed in final output)
RED                  2      (7, 13)
BLUE                 1      (1)
GREEN                3      (8, 10, 11)
RED, BLUE            3      (2, 3, 6)
RED, GREEN           2      (6, 9)
BLUE, GREEN          2      (4, 6)
RED, BLUE, GREEN     1      (6)

Кто-нибудь знает эффективный способ сделать это в R?Спасибо!

Ответы [ 2 ]

5 голосов
/ 26 сентября 2019

Вы можете использовать библиотеку venn (особенно подходит для ситуаций, когда у вас нет NA в ваших данных):

venn_table <- venn(as.list(dat))

               BLUE RED GREEN counts
                  0   0     0      0
GREEN             0   0     1      3
RED               0   1     0      2
RED:GREEN         0   1     1      1
BLUE              1   0     0      2
BLUE:GREEN        1   0     1      1
BLUE:RED          1   1     0      2
BLUE:RED:GREEN    1   1     1      1

И:

attr(venn_table, "intersections")

$GREEN
[1]  8 10 11

$RED
[1]  7 13

$`RED:GREEN`
[1] 9

$BLUE
[1]  1 NA

$`BLUE:GREEN`
[1] 4

$`BLUE:RED`
[1] 2 3

$`BLUE:RED:GREEN`
[1] 6

Включить такжеидентификаторы:

data.frame(venn_table[2:nrow(venn_table), ],
           ID = do.call("rbind", lapply(attr(venn_table, "intersections"), paste0, collapse = ",")))

               BLUE RED GREEN counts      ID
GREEN             0   0     1      3 8,10,11
RED               0   1     0      2    7,13
RED:GREEN         0   1     1      1       9
BLUE              1   0     0      2    1,NA
BLUE:GREEN        1   0     1      1       4
BLUE:RED          1   1     0      2     2,3
BLUE:RED:GREEN    1   1     1      1       6

Один из способов иметь дело с NA:

venn_table2 <- data.frame(venn_table[2:nrow(venn_table), length(venn_table), drop = FALSE],
                          ID = do.call("rbind", lapply(attr(venn_table, "intersections"), paste0, collapse = ",")))

counts <- venn_table2[1] - with(venn_table2, lengths(regmatches(ID, gregexpr("NA", ID))))

               counts
GREEN               3
RED                 2
RED:GREEN           1
BLUE                1
BLUE:GREEN          1
BLUE:RED            2
BLUE:RED:GREEN      1

И более элегантный способ иметь дело с NA (основано на комментарии @M-):

print(venn(Map(function(x) x[!is.na(x)], as.list(dat))))

               BLUE RED GREEN counts
                  0   0     0      0
GREEN             0   0     1      3
RED               0   1     0      2
RED:GREEN         0   1     1      1
BLUE              1   0     0      1
BLUE:GREEN        1   0     1      1
BLUE:RED          1   1     0      2
BLUE:RED:GREEN    1   1     1      1
2 голосов
/ 26 сентября 2019
library(dplyr)
library(tidyr)

cbind(dat, row = 1:6) %>% 
  gather(COLOR, IDs, -row) %>% 
  group_by(IDs) %>% 
  nest(COLOR, .key="COLOR") %>% 
  mutate(COLOR = sapply(COLOR, as.character)) %>% 
  drop_na %>% 
  group_by(COLOR) %>% 
  add_count(name="TOTAL") %>% 
  group_by(COLOR, TOTAL) %>% 
  nest(IDs, .key = "IDs") %>% 
  as.data.frame

#>                       COLOR TOTAL       IDs
#> 1                      BLUE     1         1
#> 2          c("BLUE", "RED")     2      2, 3
#> 3        c("BLUE", "GREEN")     1         4
#> 4 c("BLUE", "RED", "GREEN")     1         6
#> 5                       RED     2     7, 13
#> 6         c("RED", "GREEN")     1         9
#> 7                     GREEN     3 8, 10, 11


Существует более традиционный метод для работы с NA в venn упаковке:

library(purrr)
library(magrittr)
library(venn)

as.list(dat) %>%
  map(discard, is.na) %>%
  compact() %>% 
  venn() %>% 
  print

    #>                BLUE RED GREEN counts
    #>                   0   0     0      0
    #> GREEN             0   0     1      3
    #> RED               0   1     0      2
    #> RED:GREEN         0   1     1      1
    #> BLUE              1   0     0      1
    #> BLUE:GREEN        1   0     1      1
    #> BLUE:RED          1   1     0      2
    #> BLUE:RED:GREEN    1   1     1      1

Есть многодругие пакеты для venn диаграммы в R в соответствии с этим ответом .

Например, пакет VennDiagram::venn.diagram имеет переменную na, которая получает stop, remove и none.Итак, здесь мы будем использовать remove;однако, это даст нам только диаграмму, а не таблицу.Вы можете изучить другие возможности в других пакетах.

...