#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:
outer
ожидает двоичную функцию. Я предполагаю, что это была опечатка в вашем коде.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