我试图在R中创建各种距离/关联函数的矩阵。我有一个类似于cor的函数,它给出了两个向量之间的关联。现在我想采用数字向量的数据帧(或矩阵),如mtcars
,并从函数和数据框创建一个矩阵。我认为这是outer
的用途,但我没有让它发挥作用。这是尝试使用cor和mtcars
。
cor(mtcars$mpg, mtcars$cyl) #a function that gives an association between two vectors
outer(mtcars, mtcars, "cor") #the attempt to create a matrix of all vectors in a df
是的,我知道cor
可以直接执行此操作,让我们假装它不能。 cor
只找到两个向量之间的相关性。
所以最终目标是从cor(mtcars)
获得矩阵。
提前谢谢。
答案 0 :(得分:8)
您可以将outer
与一个以列名或列号作为参数的函数一起使用。
outer(
names(mtcars),
names(mtcars),
Vectorize(function(i,j) cor(mtcars[,i],mtcars[,j]))
)
答案 1 :(得分:3)
outer
并不直接取决于工作。它只会扩展其X
和Y
向量并调用cor
一次。 编辑正如@Vincent Zoonekynd所示,你可以让它适应工作。
否则,一个相当简单的循环可以解决这个问题:
m <- as.matrix(mtcars)
r <- matrix(1, ncol(m), ncol(m), dimnames=list(colnames(m), colnames(m)))
for(i in 1:(ncol(m)-1)) {
for(j in (i+1):ncol(m)) {
r[i,j] <- cor(m[,i], m[,j])
r[j,i] <- r[i,j]
}
}
all.equal(r, cor(m)) # Sanity check...
r # print resulting 11x11 correlation matrix
...这里我假设您的相关性是对称的,而cor(x,x)== 1
。
更新由于文森特的解决方案更加优雅,我不得不反对我的速度提高2倍的事实: - )
# Huge data frame (1e6 rows, 10 cols)
d <- data.frame(matrix(1:1e7, ncol=10))
# Vincent's solution
system.time(outer(
names(d),
names(d),
r <- Vectorize(function(i,j) cor(d[,i],d[,j]))
)) # 2.25 secs
# My solution
system.time({
m <- d
r <- matrix(1, ncol(m), ncol(m), dimnames=list(colnames(m), colnames(m)))
for(i in 1:(ncol(m)-1)) {
for(j in (i+1):ncol(m)) {
r[i,j] <- cor(m[,i], m[,j])
r[j,i] <- r[i,j]
}
}
}) # 1.0 secs