将函数应用于所有列的成对组合的最快方法

dmp*_*dmp 6 r data.table

给定具有任意行数和列数的数据框或矩阵,将函数应用于所有成对列组合的最快方法是什么?

例如,如果我有一个数据表:

N <- 3
K <- 3
data <- data.table(id=seq(N))
for(k in seq(K)) {
    data[[k]] <- runif(N)
}
Run Code Online (Sandbox Code Playgroud)

我想计算所有列对之间的简单差异,我可以lapply在列上循环(或):

differences = data.table(foo=seq(N))
for(var1 in names(data)) {
    for(var2 in names(data)) {
        if (var1==var2) next
        if (which(names(data)==var1)>which(names(data)==var2)) next
        combo <- paste0(var1, var2)
        differences[[combo]] <- data[[var1]]-data[[var2]]
    }
}
Run Code Online (Sandbox Code Playgroud)

但随着 K 变大,这变得异常缓慢。

我考虑过的一种解决方案是使用combn并减去它们来制作两个新数据表:

a <- data[,combn(colnames(data),2)[1,],with=F]
b <- data[,combn(colnames(data),2)[2,],with=F]
differences <- a-b
Run Code Online (Sandbox Code Playgroud)

但是随着 N 和 K 变大,这会变得非常占用内存(尽管比循环快)。

在我看来,矩阵与自身的外积可能是最好的方法,但我无法拼凑起来。如果我想应用任意函数(例如 RMSE),而不仅仅是差异,这尤其困难。

最快的方法是什么?

小智 2

如果需要先将数据放入矩阵中,可以执行以下操作:

library(data.table)

data <- matrix(runif(300*500), nrow = 300, ncol = 500)

data.DT <- setkey(data.table(c(data), colId = rep(1:500, each = 300), rowId = rep(1:300, times = 500)), colId)

diff.DT <- data.DT[
  , {
    ccl <- unique(colId)
    vv <- V1
    data.DT[colId > ccl, .(col2 = colId, V1 - vv)]
  }
  , keyby = .(col1 = colId)
]
Run Code Online (Sandbox Code Playgroud)