提问人:vp_050 提问时间:12/19/2020 最后编辑:vp_050 更新时间:12/19/2020 访问量:101
提高 R 中 ifelse-for 循环的速度,同时在循环中填充矩阵
Increase speed for a ifelse-for loop in R, while filling matrix within loop
问:
如果实际循环范围为 1000,如何提高以下循环操作的速度? 在下面的代码中:
DF3= 数据帧
OP 和 k 是 DF3 数据帧中的两列。在这里,k 取一个介于 1 到 10 之间的值。
l1 <- seq(1, 10, 1)
E<-matrix(data=0, nrow=10, ncol=10)
for (i in seq_along(l1)){
for (j in seq_along(l1)){
E[i,j]=sum(ifelse (DF3$OP[DF3$k==i]<DF3$OP[DF3$k==j],1,0))
}
}
DF3 示例:
k OP
1 60
1 30
1 38
1 46
2 29
2 35
2 13
2 82
3 100
3 72
3 63
3 45
答:
4赞
ThomasIsCoding
12/19/2020
#1
也许你可以通过使用 来简化嵌套循环,它只计算上三角矩阵的值(但它们足以获得整个矩阵中的值)for
combn
E <- matrix(data = 0, nrow = max(DF3$k), ncol = max(DF3$k))
v <- split(DF3$OP, DF3$k)
E[lower.tri(E)] <- combn(v, 2, FUN = function(x) sum(do.call("-", x) < 0))
E[upper.tri(E)] <- max(lengths(v)) - t(E)[upper.tri(E)]
E <- t(E)
最后你会得到
> E
[,1] [,2] [,3]
[1,] 0 2 3
[2,] 2 0 3
[3,] 1 1 0
数据
> dput(DF3)
structure(list(k = c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L,
3L, 3L), OP = c(60L, 30L, 38L, 46L, 29L, 35L, 13L, 82L, 100L,
72L, 63L, 45L)), class = "data.frame", row.names = c(NA, -12L
))
1赞
Cole
12/19/2020
#2
逻辑比较
DF3$OP[DF3$k==i]<DF3$OP[DF3$k==j]
意味着在所有组中,结果数量相等。如果组之间的记录数量不均匀,则计算将出现问题。k
在数据集中,每个组中有 4 条记录。这表明,与其使用数据帧,不如使用矩阵。
ncols = length(unique(DF3$k))
mat = matrix(DF3$OP, ncol = ncols)
E = matrix(0L, ncols, ncols)
for (i in seq_len(ncols)) {
x = mat[, i]
for (j in seq_len(ncols)) {
E[i, j] = sum(x < mat[, j])
}
}
E
## [,1] [,2] [,3]
## [1,] 0 2 3
## [2,] 2 0 3
## [3,] 1 1 0
1赞
Parfait
12/19/2020
#3
由于您需要具有反向重复的 by 组的成对块来进行比较,因此您实际上是在填充方形矩阵的上三角形和下三角形。因此,请考虑将数据框拆分为 OP 块,并传递到矩阵填充中。DF3$OP
DF3$k
by
combn
OP_list <- by(DF3, DF3$k, function(sub) sub$OP)
OP_list
# DF3$k: 1
# [1] 60 30 38 46
# ------------------------------------------------------------
# DF3$k: 2
# [1] 29 35 13 82
# ------------------------------------------------------------
# DF3$k: 3
E <- matrix(data=0, nrow=max(DF3$k), ncol=max(DF3$k))
# COMPARE ACROSS ALL COMBINATIONS OF K-GROUP VECTORS
E[upper.tri(E)] <- combn(OP_list, 2, function(x) sum(x[[1]] < x[[2]]))
E[lower.tri(E)] <- combn(OP_list, 2, function(x) sum(x[[1]] > x[[2]]))
E
# [,1] [,2] [,3]
# [1,] 0 2 3
# [2,] 2 0 3
# [3,] 1 1 0
应该适用于小型或大型套装。请参见:Online Demo
评论
seq(1, 2552, 1)
1:2552
seq_along(l1)
l1
sum(ifelse ( ... ,1,0))
ifelse()