对n * m矩阵的所有列组合起作用,产生m * m结果

时间:2017-06-22 21:10:18

标签: r function matrix combinations

假设我有一个函数,它接受两个向量并返回一个整数,例如一个元素的数量也在另一个向量中。像:

f <- function(v1,v2)sum(v1 %in% v2)

如何将该函数应用于n * m矩阵中m列的所有成对组合。

set.seed(1)
m <- replicate(3, sample(letters[1:10], size = 5))
dimnames(m) <- list(NULL, paste0('c', 1:ncol(m)))

现在,

> m
     [,1] [,2] [,3]
[1,] "c"  "i"  "c" 
[2,] "d"  "j"  "b" 
[3,] "e"  "f"  "f" 
[4,] "g"  "e"  "j" 
[5,] "b"  "a"  "e" 

并在前两列上执行该功能:

> f(m[,1], m[,2])
[1] 1 #'e' is shared.

如何在所有列组合上执行此操作?结果可能是am * m矩阵(其中结果在对角线周围是对称的),或者,它可以是具有v1,v2列和函数结果的长格式数据帧(例如第一行)将是c1c23

我尝试调查函数outerexpand.grid,但无法找到解决方案。

4 个答案:

答案 0 :(得分:2)

sapply(1:3, function(i) sapply(1:3, function(j) f(m[,i], m[,j])))
#     [,1] [,2] [,3]
#[1,]    5    1    3
#[2,]    1    5    3
#[3,]    3    3    5

或者以下输出可能更友好

sapply(data.frame(m), function(x1) sapply(data.frame(m), function(x2) f(x1, x2)))
#   c1 c2 c3
#c1  5  1  3
#c2  1  5  3
#c3  3  3  5

答案 1 :(得分:2)

使用expand.grid获取所有组合,然后遍历对,获得相交项的长度。

myComb <- expand.grid(colnames(m), colnames(m))

myComb$N <- apply(myComb, 1, function(i){
  length(intersect(m[, i[1]], m[, i[2]]))
  # or use your own function
  # f(m[, i[1]], m[, i[2]])
})

myComb
#   Var1 Var2 N
# 1   c1   c1 5
# 2   c2   c1 1
# 3   c3   c1 3
# 4   c1   c2 1
# 5   c2   c2 5
# 6   c3   c2 3
# 7   c1   c3 3
# 8   c2   c3 3
# 9   c3   c3 5

答案 2 :(得分:1)

我们可以使用outer

执行此操作
f1 <- function(x, y) length(intersect(m[,x], m[,y]))
res <- outer(colnames(m), colnames(m), FUN = Vectorize(f1))
dimnames(res) <-  list(colnames(m), colnames(m))
res
#   c1 c2 c3
#c1  5  1  3
#c2  1  5  3
#c3  3  3  5

答案 3 :(得分:0)

双循环也有效。我只将m转换为数据框M

f <- function(v1,v2)sum(v1 %in% v2)
set.seed(1) #Leads to different m values than you posted
m <- replicate(3, sample(letters[1:10], size = 5))
dimnames(m) <- list(NULL, paste0('c', 1:ncol(m)))

#Convert m to dataframe M
M <- as.data.frame(m)

#Initialize dataframe of answers
df <- data.frame(matrix(ncol=3, nrow=ncol(M)))

#Loop and get answers
row <- 1
for(i in 1:(ncol(M)-1)){
  for(j in 1:(ncol(M)-i)){
    df[row, 1] <- names(M)[i]
    df[row, 2] <- names(M)[i+j]
    df[row, 3] <- f(M[,i], M[,i+j])
    row <- row+1
  }
}

df
  X1 X2 X3
1 c1 c2  1
2 c1 c3  3
3 c2 c3  3