【问题标题】:R: Applying a function to all row-pairs of a matrix without for loopR:在没有for循环的情况下将函数应用于矩阵的所有行对
【发布时间】:2017-05-29 00:10:04
【问题描述】:

我想要矩阵中所有行的所有成对比较,显然双循环会起作用,但对于大型数据集来说非常昂贵。

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

如何实现?

【问题讨论】:

    标签: r vectorization


    【解决方案1】:

    我假设您正在尝试对矩阵的所有行对进行某种类型的比较。 您可以使用 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
    

    【讨论】:

    • 很好的答案!谢谢。唯一我不明白的是,示例中使用的外部函数中的 1:4、1:4?它们是输出的维度,但我认为它们应该是 FUN 的论据吗?
    • 4 是原始矩阵的行数。
    • 我有一个关于使用结果矩阵中的数据的后续问题,这里是相关矩阵,例如
    • 对不起,我的问题是我需要从每一行中检索不在 (mean-4sd, mean+4sd) 范围内的所有元素,例如 0.9 将是平均值的异常值0.6 和标准差 0.02。我想知道有没有一种优雅的方式来做到这一点?谢谢!
    • @rpylearning:您可能希望将此添加为新问题,因为它与您的原始问题没有明显关系。无论哪种方式,4sd 都不是异常值的标准度量,因此您可能也需要查看它。
    【解决方案2】:

    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))

    【讨论】:

    • 我尝试应用这种方法来获取要计算 CCF 矩阵的时间序列列表的互相关矩阵。 ccff
    • @Anusha 请分享您的示例代码(填充 X 并运行 ccff) - 将检查它。您可以使用我的联系表 gk.palem.in/Contact.html 将您的 sn-p 发给我
    • 请查看我尝试使用 mapply 的这个问题。我很想知道如何将 adply 用于一对系列的计算。 stackoverflow.com/questions/25477116/…。谢谢。
    • aaply 可用于此目的。我已经给出了示例工作代码和注释作为对您指出的问题的答案,在这里:stackoverflow.com/a/26162253/451456 谢谢。
    【解决方案3】:

    也许不像@Prasad那样通用,但在这种平方和的特殊情况下要快得多:

    dist(m)^2
    

    【讨论】:

      【解决方案4】:

      @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 会丢弃结果,那么如何将输出存储在向量中以供进一步分析?我不想只打印结果

      【讨论】:

      • 要存储输出,您可以尝试aaplyadply 而不是a_ply
      猜你喜欢
      • 2014-02-19
      • 1970-01-01
      • 2019-12-06
      • 1970-01-01
      • 2019-03-22
      • 2013-02-16
      • 2016-10-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多