2017-06-22 74 views
2

说我有一个函数,它需要两个向量并返回一个整数,例如一个元素的数量也在另一个向量中。如:n * m矩阵的所有列组合的函数产生m * m结果

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但找不到解决方案。

+1

做到这一点对于这个特定的情况下,又见'crossprod(表(男,山坳(M)))' –

回答

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 
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 
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 
+0

很好的解决方案:把你的输出'申请...'你可以很容易地制作矩阵矩阵(输出,ncol = 3)'。太糟糕OP没有指定输出格式。 – CPak

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