两个数据框之间计算相关性是否需要循环?

11

我有一组看起来像 A 和 B 的大型数据框:

A <- data.frame(A1=c(1,2,3,4,5),B1=c(6,7,8,9,10),C1=c(11,12,13,14,15 ))

  A1 B1 C1
1  1  6 11
2  2  7 12
3  3  8 13
4  4  9 14
5  5 10 15

B <- data.frame(A2=c(6,7,7,10,11),B2=c(2,1,3,8,11),C2=c(1,5,16,7,8))

  A2 B2 C2
1  6  2  1
2  7  1  5
3  7  3 16
4 10  8  7
5 11 11  8

我想创建一个向量(C),用于表示A1和A2、B1和B2以及C1和C2之间的Pearson相关性。例如,在这种情况下,这些相关性为:

[1] 0.95 0.92 0.46
3个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
14

cor接受两个数据框:

A<-data.frame(A1=c(1,2,3,4,5),B1=c(6,7,8,9,10),C1=c(11,12,13,14,15 ))

B<-data.frame(A2=c(6,7,7,10,11),B2=c(2,1,3,8,11),C2=c(1,5,16,7,8))

cor(A,B)

#           A2        B2       C2
# A1 0.9481224 0.9190183 0.459588
# B1 0.9481224 0.9190183 0.459588
# C1 0.9481224 0.9190183 0.459588

diag(cor(A,B))
#[1] 0.9481224 0.9190183 0.4595880

编辑:

以下是一些基准测试结果:

Unit: microseconds
                   expr     min       lq   median       uq      max neval
        diag(cor(A, B)) 230.292 238.4225 243.0115 255.0295  352.955   100
      mapply(cor, A, B) 267.076 281.5120 286.8030 299.5260  375.087   100
 unlist(Map(cor, A, B)) 250.053 259.1045 264.5635 275.9035 1146.140   100

编辑2:

使用更好的基准测试:

set.seed(42)
A <- as.data.frame(matrix(rnorm(10*n),ncol=n))
B <- as.data.frame(matrix(rnorm(10*n),ncol=n))

enter image description here

然而,我应该提到这些基准测试结果强烈依赖于行数。

编辑3:因为有人要求基准测试代码,所以在这里提供它。

b <- sapply(2^(1:12), function(n) {
    set.seed(42)
    A <- as.data.frame(matrix(rnorm(10*n),ncol=n))
    B <- as.data.frame(matrix(rnorm(10*n),ncol=n))

    require(microbenchmark)
    res <- print(microbenchmark(
                   diag(cor(A,B)),
                   mapply(cor, A, B),
                   unlist(Map(cor,A,B)),
                   times=10
                 ),unit="us")
    res$median
})

b <- t(b)

matplot(x=1:12,log10(b),type="l",
        ylab="log10(median [µs])", 
        xlab="log2(n)",col=1:3,lty=1)
legend("topleft", legend=c("diag(cor(A, B))", 
                           "mapply(cor, A, B)",
                           "unlist(Map(cor,A,B))"),lty=1, col=1:3)

4
请使用“diag”命令只获取他感兴趣的数值。 - sgibb
是否有类似于 cor 的函数可以给出相关性的 p 值? - dayne
你是在询问二次算法和线性算法之间的区别吗? :-) 当你只有3列时,这并不重要,但当列数达到几百时,这就很重要了。 - sds
你是如何生成基准测试的?(麻烦您编辑一下您的回答并包含代码 - 谢谢)我发现对于任何输入,diag/cor可以胜过mapply/cor非常奇怪。您能解释一下吗? - sds
1
@sds 嗯?diag非常快,这里并不重要。如果将数据框传递给cor,则会强制转换为矩阵。然后将矩阵传递给C函数。编译的代码比mapplyMap更有效率。 - Roland
显示剩余2条评论

7
您可以使用 Map 函数来实现这个功能。
Map(function(x,y) cor(x,y),A,B)
$A1
[1] 0.9481224

$B1
[1] 0.9190183

$C1
[1] 0.459588
如果您想按照@Jilber的建议获得矢量输出:
unlist(Map(function(x,y) cor(x,y),A,B))
       A1        B1        C1 
0.9481224 0.9190183 0.4595880
或者你可以直接使用:
 unlist(Map(cor,A,B))
       A1        B1        C1 
0.9481224 0.9190183 0.459588

1
由于 OP 想要一个向量,你应该使用 unlist(·) - Jilber Urbina
对于一个好的Map示例,我仍然没有完全理解R中这些函数式编程概念。 - Brandon Bertelsen

6

您可以使用另一种选择——mapply函数。

> mapply(function(x,y) cor(x,y),A,B)
       A1        B1        C1 
0.9481224 0.9190183 0.4595880 
或者像@Aaron建议的那样,只需使用mapply(cor, A, B)

3
虽然mapply(cor, A, B)已足够,但如果是我,我会这样做。 - Aaron left Stack Overflow
@Aaron,如何将这种思想应用于需要它们之间相关性的文件列表?比如A....Z? - KennyC
@KennyC:我认为最好是开始一个新的问题;需要更多的细节。 - Aaron left Stack Overflow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,