【发布时间】:2017-05-29 00:10:04
【问题描述】:
我想要矩阵中所有行的所有成对比较,显然双循环会起作用,但对于大型数据集来说非常昂贵。
我查找了隐式循环,如apply() 等,但不知道如何避免内部循环。
如何实现?
【问题讨论】:
标签: r vectorization
我想要矩阵中所有行的所有成对比较,显然双循环会起作用,但对于大型数据集来说非常昂贵。
我查找了隐式循环,如apply() 等,但不知道如何避免内部循环。
如何实现?
【问题讨论】:
标签: r vectorization
我假设您正在尝试对矩阵的所有行对进行某种类型的比较。
您可以使用 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
【讨论】:
outer() 如果您愿意进行自我比较 - 例如 1-1 和 2-2 等...(矩阵中的对角线值),则可以正常工作。 outer() 也执行 1-2 和 2-1 比较。
大多数时候成对比较只需要三角比较,不需要自我比较和镜像比较。要实现三角比较,请使用combn() 方法。
这是一个示例输出,用于显示 outer() 和 combn() 之间的区别
> v <- c(1,2,3,4)
> outer(v, v, function(x, y) print(paste(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"
你可以在上面看到矩阵的“上三角”部分。
Outer() 当你有两个不同的向量来做成对操作时更合适。对于在单个向量中执行成对操作,您通常可以使用 combn。
例如,如果你正在做outer(x,x,...),那么你可能做错了 - 你应该考虑combn(length(x),2))
【讨论】:
aaply 可用于此目的。我已经给出了示例工作代码和注释作为对您指出的问题的答案,在这里:stackoverflow.com/a/26162253/451456 谢谢。
也许不像@Prasad那样通用,但在这种平方和的特殊情况下要快得多:
dist(m)^2
【讨论】:
@Gopalkrishna Palem
我喜欢你的解决方案!但是,我认为您应该使用 combn(v, 2) 而不是 combn(length(v), 2)。 combn(length(v), 2) 只迭代 v 的 indecies
> 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"
所以最终的结果是正确的commn(v, 2)。
如果我们有一个数据框,我们可以使用索引将函数应用于成对行:
> 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
但是,a_ply 会丢弃结果,那么如何将输出存储在向量中以供进一步分析?我不想只打印结果
【讨论】:
aaply 或adply 而不是a_ply