Пользовательская функция для пар столбцов матрицы

#r

Вопрос:

Добрый день ,

Предположим, что у нас есть следующая матрица :

 > dput(tnn)
structure(c(1L, 19L, 5L, 6L, 10L, 2L, 4L, 7L, 12L, 1L, 3L, 4L, 
8L, 13L, 1L, 4L, 15L, 16L, 2L, 3L, 5L, 6L, 14L, 1L, 15L, 5L, 
6L, 14L, 1L, 15L, 7L, 2L, 9L, 17L, 4L, 8L, 3L, 9L, 18L, 4L, 9L, 
10L, 11L, 4L, 7L, 9L, 10L, 11L, 1L, 15L, 9L, 10L, 11L, 1L, 15L, 
12L, 2L, 14L, 17L, 4L, 13L, 3L, 14L, 18L, 4L, 5L, 6L, 14L, 4L, 
12L, 4L, 15L, 16L, 5L, 6L, 4L, 15L, 16L, 5L, 6L, 17L, 7L, 12L, 
19L, 2L, 18L, 8L, 13L, 19L, 3L, 1L, 19L, 9L, 14L, 17L), .Dim = c(5L, 
19L))

> tnn
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [,15] [,16] [,17] [,18]
[1,]    1    2    3    4    5    5    7    8    9     9     9    12    13     5     4     4    17    18
[2,]   19    4    4   15    6    6    2    3   10    10    10     2     3     6    15    15     7     8
[3,]    5    7    8   16   14   14    9    9   11    11    11    14    14    14    16    16    12    13
[4,]    6   12   13    2    1    1   17   18    4     1     1    17    18     4     5     5    19    19
[5,]   10    1    1    3   15   15    4    4    7    15    15     4     4    12     6     6     2     3
     [,19]
[1,]     1
[2,]    19
[3,]     9
[4,]    14
[5,]    17
 

Я хочу рассчитать длину пересечения для каждой пары столбцов. Например :

 > intersect(tnn[,1],tnn[,19])
[1]  1 19
> length(intersect(tnn[,1],tnn[,19]))
[1] 2
 

Для этого я попытался :

 custom_fun<-function(data,x,y){
return(length(intersect(data[,x],data[,y])))
}
outer(1:ncol(tnn),1:ncol(tnn),function(tnn,x,y) custom_fun(tnn,x,y))
 
 

Но я получил следующую ошибку :

 Error in data[, x] : incorrect number of dimensions 
 

Спасибо вам за помощь !

Комментарии:

1. Итак, каким будет ваш формат вывода?

Ответ №1:

  1. outer ожидает двоичную функцию. Я предполагаю, что это была опечатка в вашем коде.
  2. outer обрабатывает переданную ему функцию как векторизованную. Ваша функция не является (потому intersection что не является). Но вы можете векторизовать его, используя mapply :
     cols = seq_len(ncol(tnn))
    outer(cols, cols, function (x, y) mapply(custom_fun, list(tnn), x, y))
     

Комментарии:

1. Да, это именно то, что я ищу ! Но у меня есть вопрос : я знаю, что mapply используется с 3 аргументами. Что это значит : mapply(пользовательский, список(tnn), 1, 19) ?

2. Обычно mapply используется как : mapply(функция , vec1 , vec2 )

3. mapply может использоваться с произвольным числом аргументов, а не только с тремя. Он пытается рассматривать все аргументы, кроме первого, как векторы одинакового размера, и перебирает их параллельно. Это list(…) предотвращает обработку первого аргумента как вектора размером > 1. Вместо mapply этого теперь он видит список размером 1, поэтому он перерабатывает единственный элемент внутри этого списка и передает его без изменений любому вызову custom_fun .

Ответ №2:

Мы можем использовать combn ложь ниже

 unlist(
  combn(data.frame(tnn),
    2,
    FUN = function(...) setNames(length(do.call(intersect, unname(...))), toString(names(...))),
    simplify = FALSE
  )
)
 

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

  V1, V2   V1, V3   V1, V4   V1, V5   V1, V6   V1, V7   V1, V8   V1, V9 
       1        1        0        3        3        0        0        1
 V1, V10  V1, V11  V1, V12  V1, V13  V1, V14  V1, V15  V1, V16  V1, V17
       2        2        0        0        2        2        2        1
 V1, V18  V1, V19   V2, V3   V2, V4   V2, V5   V2, V6   V2, V7   V2, V8
       1        2        2        2        1        1        3        1 
  V2, V9  V2, V10  V2, V11  V2, V12  V2, V13  V2, V14  V2, V15  V2, V16
       2        1        1        3        1        2        1        1
 V2, V17  V2, V18  V2, V19   V3, V4   V3, V5   V3, V6   V3, V7   V3, V8
       3        0        1        2        1        1        1        3
  V3, V9  V3, V10  V3, V11  V3, V12  V3, V13  V3, V14  V3, V15  V3, V16
       1        1        1        1        3        1        1        1
 V3, V17  V3, V18  V3, V19   V4, V5   V4, V6   V4, V7   V4, V8   V4, V9
       0        3        1        1        1        2        2        1
 V4, V10  V4, V11  V4, V12  V4, V13  V4, V14  V4, V15  V4, V16  V4, V17
       1        1        2        2        1        3        3        1
 V4, V18  V4, V19   V5, V6   V5, V7   V5, V8   V5, V9  V5, V10  V5, V11
       1        0        5        0        0        0        2        2
 V5, V12  V5, V13  V5, V14  V5, V15  V5, V16  V5, V17  V5, V18  V5, V19
       1        1        3        3        3        0        0        2
  V6, V7   V6, V8   V6, V9  V6, V10  V6, V11  V6, V12  V6, V13  V6, V14
       0        0        0        2        2        1        1        3
 V6, V15  V6, V16  V6, V17  V6, V18  V6, V19   V7, V8   V7, V9  V7, V10
       3        3        0        0        2        2        3        1
 V7, V11  V7, V12  V7, V13  V7, V14  V7, V15  V7, V16  V7, V17  V7, V18
       1        3        1        1        1        1        3        0
 V7, V19   V8, V9  V8, V10  V8, V11  V8, V12  V8, V13  V8, V14  V8, V15
       2        2        1        1        1        3        1        1
 V8, V16  V8, V17  V8, V18  V8, V19  V9, V10  V9, V11  V9, V12  V9, V13
       1        0        3        1        3        3        1        1
 V9, V14  V9, V15  V9, V16  V9, V17  V9, V18  V9, V19 V10, V11 V10, V12
       1        1        1        1        0        1        5        0
V10, V13 V10, V14 V10, V15 V10, V16 V10, V17 V10, V18 V10, V19 V11, V12
       0        0        1        1        0        0        2        0 
V11, V13 V11, V14 V11, V15 V11, V16 V11, V17 V11, V18 V11, V19 V12, V13
       0        0        1        1        0        0        2        2
V12, V14 V12, V15 V12, V16 V12, V17 V12, V18 V12, V19 V13, V14 V13, V15
       3        1        1        3        0        2        2        1
V13, V16 V13, V17 V13, V18 V13, V19 V14, V15 V14, V16 V14, V17 V14, V18
       1        0        3        1        3        3        1        0
V14, V19 V15, V16 V15, V17 V15, V18 V15, V19 V16, V17 V16, V18 V16, V19
       1        5        0        0        0        0        0        0
V17, V18 V17, V19 V18, V19
       1        2        1
 

Ответ №3:

подход с обратной стороны

 tnn <- structure(c(1L, 19L, 5L, 6L, 10L, 2L, 4L, 7L, 12L, 1L, 3L, 4L, 
                   8L, 13L, 1L, 4L, 15L, 16L, 2L, 3L, 5L, 6L, 14L, 1L, 15L, 5L, 
                   6L, 14L, 1L, 15L, 7L, 2L, 9L, 17L, 4L, 8L, 3L, 9L, 18L, 4L, 9L, 
                   10L, 11L, 4L, 7L, 9L, 10L, 11L, 1L, 15L, 9L, 10L, 11L, 1L, 15L, 
                   12L, 2L, 14L, 17L, 4L, 13L, 3L, 14L, 18L, 4L, 5L, 6L, 14L, 4L, 
                   12L, 4L, 15L, 16L, 5L, 6L, 4L, 15L, 16L, 5L, 6L, 17L, 7L, 12L, 
                   19L, 2L, 18L, 8L, 13L, 19L, 3L, 1L, 19L, 9L, 14L, 17L), .Dim = c(5L, 
                                                                                    19L))
library(tidyverse)

expand.grid(seq_len(ncol(tnn)), seq_len(ncol(tnn))) %>% as.data.frame() %>%
  mutate(des_len = map2_int(Var1, Var2, ~length(intersect(tnn[,.x], tnn[, .y]))))
#>     Var1 Var2 des_len
#> 1      1    1       5
#> 2      2    1       1
#> 3      3    1       1
#> 4      4    1       0
#> 5      5    1       3
#> 6      6    1       3
....
 

Вместо того, чтобы иметь перестановки, если вы хотите иметь комбинации, вы можете сделать что-то вроде этого

 combn(seq_len(ncol(tnn)), 2) %>% t %>% as.data.frame() %>%
  mutate(des_len = map2_int(V1, V2, ~length(intersect(tnn[,.x], tnn[,.y]))))

 

Комментарии:

1. При использовании tidyverse вы могли бы использовать tidyr::expand вместо expand.grid .

2. Конечно, @KonradRudolph, спасибо за информацию. Я буду иметь это в виду в следующий раз. 🙂

3. Обычно я обычно стараюсь избегать расширения.сетки для большого количества столбцов / строк. Эта функция создает комбинации целых чисел. После этого мы перебираем пары с помощью apply !

4. Спасибо вам за помощь !

5. @TouMou, см. Пересмотренный ответ, я добавил стратегию только для комбинаций вместо перестановок.

Ответ №4:

Другой вариант использования genfilter :

 library(data.table)
library(genefilter)


tnn=structure(c(1L, 19L, 5L, 6L, 10L, 2L, 4L, 7L, 12L, 1L, 3L, 4L, 
8L, 13L, 1L, 4L, 15L, 16L, 2L, 3L, 5L, 6L, 14L, 1L, 15L, 5L, 
6L, 14L, 1L, 15L, 7L, 2L, 9L, 17L, 4L, 8L, 3L, 9L, 18L, 4L, 9L, 
10L, 11L, 4L, 7L, 9L, 10L, 11L, 1L, 15L, 9L, 10L, 11L, 1L, 15L, 
12L, 2L, 14L, 17L, 4L, 13L, 3L, 14L, 18L, 4L, 5L, 6L, 14L, 4L, 
12L, 4L, 15L, 16L, 5L, 6L, 4L, 15L, 16L, 5L, 6L, 17L, 7L, 12L, 
19L, 2L, 18L, 8L, 13L, 19L, 3L, 1L, 19L, 9L, 14L, 17L), .Dim = c(5L, 
19L))


custom_fun<-function(x,y){
return(length(intersect(x,y)))
}

dist2(as.matrix(tnn),custom_fun,diagonal = 0)

      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
 [1,]    0    1    1    0    3    3    0    0    1     2     2     0     0
 [2,]    1    0    2    2    1    1    3    1    2     1     1     3     1
 [3,]    1    2    0    2    1    1    1    3    1     1     1     1     3
 [4,]    0    2    2    0    1    1    2    2    1     1     1     2     2
 [5,]    3    1    1    1    0    5    0    0    0     2     2     1     1
 [6,]    3    1    1    1    5    0    0    0    0     2     2     1     1
 [7,]    0    3    1    2    0    0    0    2    3     1     1     3     1
 [8,]    0    1    3    2    0    0    2    0    2     1     1     1     3
 [9,]    1    2    1    1    0    0    3    2    0     3     3     1     1
[10,]    2    1    1    1    2    2    1    1    3     0     5     0     0
[11,]    2    1    1    1    2    2    1    1    3     5     0     0     0
[12,]    0    3    1    2    1    1    3    1    1     0     0     0     2
[13,]    0    1    3    2    1    1    1    3    1     0     0     2     0
[14,]    2    2    1    1    3    3    1    1    1     0     0     3     2
[15,]    2    1    1    3    3    3    1    1    1     1     1     1     1
[16,]    2    1    1    3    3    3    1    1    1     1     1     1     1
[17,]    1    3    0    1    0    0    3    0    1     0     0     3     0
[18,]    1    0    3    1    0    0    0    3    0     0     0     0     3
[19,]    2    1    1    0    2    2    2    1    1     2     2     2     1
      [,14] [,15] [,16] [,17] [,18] [,19]
 [1,]     2     2     2     1     1     2
 [2,]     2     1     1     3     0     1
 [3,]     1     1     1     0     3     1
 [4,]     1     3     3     1     1     0
 [5,]     3     3     3     0     0     2
 [6,]     3     3     3     0     0     2
 [7,]     1     1     1     3     0     2
 [8,]     1     1     1     0     3     1
 [9,]     1     1     1     1     0     1
[10,]     0     1     1     0     0     2
[11,]     0     1     1     0     0     2
[12,]     3     1     1     3     0     2
[13,]     2     1     1     0     3     1
[14,]     0     3     3     1     0     1
[15,]     3     0     5     0     0     0
[16,]     3     5     0     0     0     0
[17,]     1     0     0     0     1     2
[18,]     0     0     0     1     0     1
[19,]     1     0     0     2     1     0