I have a list, say exm = list( elm1=c('a', 'b'), elm2=c('b', 'c', 'd'), elm3=c('b', 'c', 'd', 'e'))
. I want to apply a function on every combination of two elements from exm
, e.g., length( intersect( exm$elm1, exm$elm2 ) )
. The result should be a symmetric matrix. The function outer
seems to do this job, but it works only for vector, not list. Any idea to do this?
Asked
Active
Viewed 962 times
5

yliueagle
- 1,191
- 1
- 7
- 22
2 Answers
6
How about the following:
exm = list( elm1=c('a', 'b'), elm2=c('b', 'c', 'd'), elm3=c('b', 'c', 'd', 'e'))
#Use mapply to vectorise your function
int2 <- function(x,y) mapply(function(x,y) {length( intersect( x, y ) )},
exm[x], exm[y])
#Use outer on the indices of exm, rather than exm itself
s <- seq_along(exm)
outer(s,s,int2)
# [,1] [,2] [,3]
# [1,] 2 1 1
# [2,] 1 3 3
# [3,] 1 3 4

Miff
- 7,486
- 20
- 20
0
Here is another approach:
# Data
exm = list( elm1=c('a', 'b'), elm2=c('b', 'c', 'd'), elm3=c('b', 'c', 'd', 'e'))
# Set up possible comparisons
combinations <- data.frame(t(combn(names(exm), 2)))
# Caculate overlap
for (i in 1:nrow(combinations)){
combinations$length[[i]] <- length(intersect(exm[[combinations[i,1]]], exm[[combinations[i,2]]]))
}
# > combinations
# X1 X2 length
# 1 elm1 elm2 1
# 2 elm1 elm3 1
# 3 elm2 elm3 3
# Matrix output
m.out <- matrix(ncol=length(exm), nrow=length(exm), dimnames = list(names(exm),names(exm)))
# Fil in overlap figures
m.out[cbind(combinations$X1, combinations$X2)] <- combinations$length
m.out[cbind(combinations$X2, combinations$X1)] <- combinations$length
# Fill in length of vector itself as diagonal - if necessary
diag(m.out) <- unlist(lapply(exm, length))
# > m.out
# elm1 elm2 elm3
# elm1 2 1 1
# elm2 1 3 3
# elm3 1 3 4

majom
- 7,863
- 7
- 55
- 88