我有一个双循环,我不仅不喜欢,而且需要14天才能在我的计算机上运行,因为它会超过3200条记录和1090个变量,每次迭代大约.12。
较小的可重现位。它只是检查两个记录之间相同列中的数量,不包括NA。然后它将结果附加到原始数据框。
y <- data.frame(c(1,2,1,NA,NA),c(3,3,3,4,NA),c(5,4,5,7,7),c(7,8,7,9,10))
resultdf <- NULL
for(i in 1:nrow(y))
{
results <- NULL
for(j in 1:nrow(y))
{
results <- c(results,sum((y[i,]==y[j,]),na.rm=TRUE))
}
resultdf <- cbind(resultdf,results)
}
y <- cbind(y,resultdf)
我有重复的计算,可以避免大约7天。
如果我理解正确,一些应用函数在C中可能更快。虽然我无法上班。如果有一个运行速度更快的包,我也很好奇。任何人都可以帮助加快计算速度吗?
谢谢!
答案 0 :(得分:3)
这是另一种解决方案,使用outer
。
f <- function(i,j) sum(y[i,] == y[j,], na.rm=TRUE)
d <- outer( 1:nrow(y), 1:nrow(y), Vectorize(f) )
答案 1 :(得分:3)
我已根据您的规格创建数据,并使用@BenBolker关于使用矩阵的建议:
> y <- matrix(sample(c(1:9, NA), 3200 * 1090, replace = TRUE),
+ nrow = 3200, ncol = 1090)
并比较了三种不同实现的计算时间:
@Andrei建议 f1
:
> f1 <- function(y)apply(y, 1, function(r1)
+ apply(y, 1, function(r2)sum(r1==r2, na.rm=TRUE)))
> system.time(r1 <- f1(y))
user system elapsed
523.51 0.77 528.73
@VincentZoonekynd建议 f2
:
> f2 <- function(y) {
+ f <- function(i,j) sum(y[i,] == y[j,], na.rm=TRUE)
+ d <- outer( 1:nrow(y), 1:nrow(y), Vectorize(f) )
+ return(d)
+ }
> system.time(r2 <- f2(y))
user system elapsed
658.94 1.96 710.67
f3
是@BenBolker建议的上三角形的双循环。它也比你的OP更有效率,因为它预先分配了输出矩阵:
> f3 <- function(y) {
+ result <- matrix(NA, nrow(y), nrow(y))
+ for (i in 1:nrow(y)) {
+ row1 <- y[i, ]
+ for (j in i:nrow(y)) {
+ row2 <- y[j, ]
+ num.matches <- sum(row1 == row2, na.rm = TRUE)
+ result[i, j] <- num.matches
+ result[j, i] <- num.matches
+ }
+ }
+ return(result)
+ }
> system.time(r3 <- f3(y))
user system elapsed
167.66 0.08 168.72
所以双循环是所有三个循环中最快的,尽管不像其他两个答案那样优雅和紧凑。
答案 2 :(得分:2)
确实,你可以使用apply函数。鉴于早期暗示矩阵运行得更快,我会尝试:
ym <- as.matrix(y)
resultdf <- apply(ym, 1, function(r1) apply(ym, 1, function(r2) sum(r1==r2, na.rm=TRUE)))
答案 3 :(得分:1)
你可以摆脱内循环(使用来自@ flodel的答案的y
和f3
):
ty <- t(y)
ix <- rep(1:nrow(y),each = ncol(y))
f4 <- function(y){
result <- matrix(0L, nrow(y), nrow(y))
for(r in 1:nrow(y))
result[r,] <- rowsum(as.numeric(ty == y[r,]), ix, na.rm = T)
result
}
> system.time(out <- f4(y))
user system elapsed
52.616 21.061 74.000
> system.time(out <- f3(y))
user system elapsed
244.751 0.136 244.954
>
它实际上做了两次相同的计算,但仍然快了5倍。通过使用rowsum的内部工作,你可以使它再快4倍。有关示例,请参阅此question。