R:将函数应用于矩阵的所有行对,而不使用for循环

R:将函数应用于矩阵的所有行对,而不使用for循环,r,vectorization,R,Vectorization,我希望对矩阵中的所有行进行两两比较,显然,double for循环可以工作,但对于大型数据集来说非常昂贵 我查找了隐式循环,比如apply(),但不知道如何避免内部循环 如何实现呢?我假设您正在尝试对矩阵的所有行对进行某种类型的比较。 您可以使用outer()遍历所有行索引对,并应用矢量化 每个行对的比较函数。例如,您可以计算所有行对之间的平方欧氏距离,如下所示: m <- matrix(1:12,4,3) > outer(1:4,1:4, FUN = Vectorize(

我希望对矩阵中的所有行进行两两比较,显然,double for循环可以工作,但对于大型数据集来说非常昂贵

我查找了隐式循环,比如
apply()
,但不知道如何避免内部循环


如何实现呢?

我假设您正在尝试对矩阵的所有行对进行某种类型的比较。 您可以使用
outer()
遍历所有行索引对,并应用矢量化 每个行对的比较函数。例如,您可以计算所有行对之间的平方欧氏距离,如下所示:

m <- matrix(1:12,4,3)     
> outer(1:4,1:4, FUN = Vectorize( function(i,j) sum((m[i,]-m[j,])^2 )) )
     [,1] [,2] [,3] [,4]
[1,]    0    3   12   27
[2,]    3    0    3   12
[3,]   12    3    0    3
[4,]   27   12    3    0
m外部(1:4,1:4,FUN=Vectorize(函数(i,j)和((m[i,]-m[j,])^2)))
[,1] [,2] [,3] [,4]
[1,]    0    3   12   27
[2,]    3    0    3   12
[3,]   12    3    0    3
[4,]   27   12    3    0

可能不像@Prasad那样通用,但在平方和的特殊情况下,速度要快得多:

dist(m)^2
outer()。。。(矩阵中的对角线值)。此外,outer()还执行1-2和2-1比较

大多数情况下,成对比较只需要三角比较,而不需要自比较和镜像比较。要实现三角形比较,请使用
combn()
方法

下面是一个示例输出,显示
outer()
combn()之间的差异

>v外部(v,v,函数(x,y)打印(粘贴(x,“-”,y)))
[1] "1 - 1" "2 - 1" "3 - 1" "4 - 1" "1 - 2" "2 - 2" "3 - 2" "4 - 2" "1 - 3" "2 - 3" "3 - 3" "4 - 3" "1 - 4" "2 - 4" "3 - 4" "4 - 4"
注意上面的“1-1”自我比较。以及“1-2”和“2-1”镜像比较。将其与以下内容进行对比:

> v <- c(1,2,3,4)
> allPairs <- combn(length(v), 2) # choose a pair from 1:length(v)
> a_ply(combn(length(v), 2), 2, function(x) print(paste(x[1],"--",x[2]))) # iterate over all pairs
[1] "1 -- 2"
[1] "1 -- 3"
[1] "1 -- 4"
[1] "2 -- 3"
[1] "2 -- 4"
[1] "3 -- 4" 
>v所有对a#u ply(combn(长度(v),2),2,函数(x)打印(粘贴(x[1],“-”,x[2]))#迭代所有对
[1] "1 -- 2"
[1] "1 -- 3"
[1] "1 -- 4"
[1] "2 -- 3"
[1] "2 -- 4"
[1] "3 -- 4" 
你可以在上面看到矩阵的“上三角”部分

当有两个不同的向量进行成对运算时,Outer()更合适。对于在单个向量中执行成对操作,通常可以使用combn

例如,如果你正在执行<代码>外(x,x,…)< /代码>,那么你可能做得不对——你应该考虑<代码> COMBN(长度(x),2))< /C> < /P> < P> @ GopalRISHHNA PALEM/P > 我喜欢你的解决方案!但是,我认为应该使用combn(v,2)而不是combn(length(v),2)。combn(长度(v),2)仅迭代v的索引

> v <- c(3,4,6,7)
> combn(v, 2)
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    3    3    3    4    4    6
[2,]    4    6    7    6    7    7

> combn(length(v), 2)
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    1    1    2    2    3
[2,]    2    3    4    3    4    4

> a_ply(combn(v, 2), 2, function(x) print(paste(x[1],"--",x[2])) )
[1] "3 -- 4"
[1] "3 -- 6"
[1] "3 -- 7"
[1] "4 -- 6"
[1] "4 -- 7"
[1] "6 -- 7"
> a_ply(combn(length(v), 2), 2, function(x) print(paste(x[1],"--",x[2])) )
[1] "1 -- 2"
[1] "1 -- 3"
[1] "1 -- 4"
[1] "2 -- 3"
[1] "2 -- 4"
[1] "3 -- 4"

但是,应用程序将丢弃结果,因此如何将输出存储在向量中以供进一步分析?我不想只打印结果

很好的答案!谢谢我唯一不明白的是,1:4,1:4,在例子中使用的外部函数中?它们是输出的维度,但我认为它们应该是有趣的参数吗?4是原始矩阵中的行数。对于使用结果矩阵中的数据,我有一个后续问题,这是相关矩阵,例如,对不起,我的问题是我需要检索不在范围内的每一行中的所有元素(平均值-4sd,平均值+4sd)从那一行开始,例如0.9将是平均值为0.6、sd为0.02的异常值。我想知道有没有一种优雅的方法可以做到这一点?谢谢!@rpylearning:您可能想将其作为一个新问题添加,因为它与您原来的问题没有明显的关系。无论哪种方法,4sd都不是异常值的标准度量,因此您可能也需要查看它。要存储输出时,您可以尝试
aaply
adply
而不是
a\u ply
我尝试应用此方法获取时间序列列表的互相关矩阵,我想在其中计算CCF矩阵。ccff@Anusha请共享您的示例代码(填充X并运行ccff)-我会检查的。您可以使用我的联系方式将您的代码片段发送给我。请查看我试图使用mapply的问题。我很想知道如何使用adply对一对系列进行计算。谢谢。
aaply
可以用于此目的。我已经给出了示例工作代码和注释,作为对您指示问题的回答n、 这里:谢谢。
> v <- c(3,4,6,7)
> combn(v, 2)
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    3    3    3    4    4    6
[2,]    4    6    7    6    7    7

> combn(length(v), 2)
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    1    1    2    2    3
[2,]    2    3    4    3    4    4

> a_ply(combn(v, 2), 2, function(x) print(paste(x[1],"--",x[2])) )
[1] "3 -- 4"
[1] "3 -- 6"
[1] "3 -- 7"
[1] "4 -- 6"
[1] "4 -- 7"
[1] "6 -- 7"
> a_ply(combn(length(v), 2), 2, function(x) print(paste(x[1],"--",x[2])) )
[1] "1 -- 2"
[1] "1 -- 3"
[1] "1 -- 4"
[1] "2 -- 3"
[1] "2 -- 4"
[1] "3 -- 4"
> df
  x  y
1 4  8
2 5  9
3 6 10
4 7 11

a_ply(combn(nrow(df), 2), 2, function(x) print(df[x[1],] - df[x[2],]))
   x  y
1 -1 -1
   x  y
1 -2 -2
   x  y
1 -3 -3
   x  y
2 -1 -1
   x  y
2 -2 -2
   x  y
3 -1 -1