我有5个表,我想找到一些满足一些要求的组合。通过使用矩阵乘法创建所有可能的组合,然后选择满足我需求的行,我可以轻松地解决下面的数据。问题是我的原始问题包括5个表,每个表有200行。如果生成所有可能的组合,则需要几百gb的ram。
所以我尝试了这个:
x1 <- seq(1,10,1)
x2 <- seq(5,15,3)
x3 <- seq(2,11,1)
x4 <- seq(1,5,1)
x5 <- seq(1,20,2)
哪个应该满足:x1&lt; x2和x1 < X3。
nm <- data.frame(matrix(NA,1,5))
for(a in 1:length(x1)){
for(s in 1:length(x2)){
for(d in 1:length(x3)){
for(f in 1:length(x4)){
for(g in 1:length(x5)){
l1 <- x1[a]
l2 <- x2[s]
if(l1 < l2){
l3 <- x3[d]
if(l1 < l3){
l4 <- x4[f]
l5 <- x5[g]
fy <- c()
fy[1] <- l1
fy[2] <- l2
fy[3] <- l3
fy[4] <- l4
fy[5] <- l5
nm <- rbind(nm, fy)
}}}}}}}
在我原来的问题中,我有更多if语句,我希望这会提高速度。但我现在已经运行了大约24小时,但仍未完成。上面的问题花了我大约10s,这让我觉得它卡住了。
答案 0 :(得分:2)
两个问题:
巨大的问题是你在循环中生长一个对象。这是最慢的操作,因为涉及巨大的操作系统开销。您需要预先分配对象,并且只在必要时将其增长为块。
中等问题是您使用data.frame来存储结果。 Data.frames很有用,但很慢。改为使用矩阵。
nm1 <- matrix(nrow = 1e3, ncol = 5) #adjust the chunk size to a reasonable estimate
rx <- 1
for(a in 1:length(x1)){
for(s in 1:length(x2)){
for(d in 1:length(x3)){
for(f in 1:length(x4)){
for(g in 1:length(x5)){
l1 <- x1[a]
l2 <- x2[s]
if(l1 < l2){
l3 <- x3[d]
if(l1 < l3){
l4 <- x4[f]
l5 <- x5[g]
if(rx > nrow(nm1)) nm1 <- rbind(nm1, matrix(nrow = 1e3, ncol = 5))
nm1[rx, 1] <- l1
nm1[rx, 2] <- l2
nm1[rx, 3] <- l3
nm1[rx, 4] <- l4
nm1[rx, 5] <- l5
rx <- rx + 1
}}}}}}}
nm1 <- nm1[seq_len(rx - 1),]
时序:
Unit: milliseconds
expr min lq mean median uq max neval cld
mod() 589.2437 591.1576 594.4138 593.3678 595.0909 603.2087 5 a
original() 4934.4981 4952.4502 4980.6414 4953.3183 4985.7943 5077.1463 5 b
我们在没有真正开始考虑算法的情况下获得了10倍的性能提升。如果您有更多的data.frame增长迭代,这个因素会变得更大。如果这仍然太慢,您可以尝试使用编译器包对代码进行字节编译。使用Rcpp实现实际编译代码也是微不足道的。但是,您应该根据不断增加的迭代次数进行基准测试,并根据实际问题推断时间。您可能需要找到比蛮力更好的算法,或者考虑是否确实需要这样做。