如何自定义外部和Vectorize函数?

时间:2014-03-25 13:21:44

标签: r matrix distance apply

一个月前我曾问过类似的问题。请参阅 Count the occurrences of unequal numbers from a data frame

我使用outerVectorize函数解决了这个问题。我的解决方案如下:

dist_mat<- outer(1:nrow(df),1:nrow(df), 
                FUN = Vectorize( function(i,j) sum(df[i,]!=df[j,]))) 

这很完美,但现在我有一个超出我的内存大小的巨大矩阵。

在我得到dist_mat后,对于每一行,我计算的列数小于或等于2,这是我现在无法做到的。所以,我想知道我是否可以在外部函数中组合计数操作以避免内存问题。我的结果只是一个向量。

提前谢谢!

2 个答案:

答案 0 :(得分:1)

虽然这并没有严格回答您的问题,但您应该避免使用outer并使用以下内容:

tot.rows <- nrow(df)
res <- numeric(tot.rows)
for(i in 1:tot.rows) 
  for(j in 1:tot.rows) 
    res[[i]] <- res[[i]] + (sum(df[i,] != df[j,]) <= 2)

outer会从开始时预分配i * j矩阵,因此您在使用外部时很难解决问题。如果您的结果实际上是与数据框长度相同的矢量,那么您不需要outer在您的应用中生成尺寸为nrow(df) * nrow(df)的矩阵。

上述算法将运行与outer相同的计算次数,但每行重复使用相同的内存空间,因为您关心的是最终计数,因此它应该适合内存。 它也应该具有与外部相当的速度(这是我测试过的玩具示例)。矢量化操作很棒,只要你真的需要计算每个值,并且有内存来处理像outer这样的完全扩展,但它们不一定是所有内容的答案。

正如其他人在上一个答案中指出的那样,你可以修改代码,这样你就不会计算对角线或矩阵的一个三角形,因为距离计算是对称的,这应该大致减半计算时间。

答案 1 :(得分:1)

如果您有矩阵DF,那么

apply(DF, 2, function(y) sum(colSums(DF==y) < 2))

可能有效吗? DF==y将每列与apply中的目标列进行比较,colSums然后找出该列对中有多少行相等,然后将其与2(目标)进行比较作为DF == y的一部分,我总是把它作为自身的一部分进行比较,所以我考虑到了 - 你可能需要解决这个问题,这取决于你的'2'阈值是否包括自我比较)。最后sum计算满足&lt; 2阈值的列数。

假设您不需要中间距离矩阵,它完全重新考虑了代码。