r 中带约束的对角线和

Diagonal sum with constraints in r

我想提取具有两个约束的单元格。

首先,如果 sum(data[i,j+@])<5,则提取数据[i,j+@],否则提取数据[i+1,j]。

其次,我想设置每一行的约束值为5,如果到第二列的总和大于10,我想在下一行工作。起始行可以从5开始。

配合下图更容易理解

绿色的是我想要的作品的第一次迭代,红色和黄色分别是第二次和第三次迭代。

下面是我想要的结果

X1  X2  X3  X4  X5  X6  X7  X8  X9
5   1.847652137 1.593196753 1.038744382 2.392577214 1.929800297 2.00485602  1.365284847 2.071210757 0.961210097
10  1.844405755 1.796177057 1.000318509 2.236319316 1.993847864 2.06124419  1.334352788 2.136264508 1.187134575
15  1.840050479 1.917357779 1.017851743 2.212746581 2.092042634 1.94601942  1.320106097 2.029994348 1.214182727
20  1.909398459 1.737023355 0.998872288 2.199635485 2.112443388 1.945944311 1.264014072 2.101753344 1.221846304
25  1.835888833 1.500481202 0.977172242 2.252597257 1.9836639   1.981422844 1.312695726 2.059200235 1.186026763
30  1.864937958 1.702083702 0.824693691 2.34185367  2.005003283 2.042903214 1.329264708 2.093476876 1.200883904
35  1.860653591 1.797731242 0.950537406 2.245353372 1.994555492 1.825519322 1.355424824 2.156744119 1.175993981
40  1.884274248 1.635847889 1.169642735 2.269898328 1.975265537 1.553298242 1.615854357 2.05323242  1.098031592
45  1.886826057 1.811210946 1.061251733 2.280645314 1.988672647 1.557977089 1.66754175  2.044207552 1.0112728
50  1.831184163 1.894325674 0.840784273 2.271033072 1.939068714 1.637609662 1.661725542 2.014112901 0.921453048
55  1.814208298 1.506889498 0.882503502 2.2606704   1.867075707 1.606874174 1.70215241  2.082384915 0.94171228
60  1.840268898 1.540609758 0.984783168 2.245115137 1.845533017 1.584807408 1.635959069 2.064869319 0.950706804
65  1.83516395  1.373207762 0.822749722 2.241155251 1.900521615 1.564088673 1.604834287 2.041777787 0.954724586
70  1.815817966 1.844931506 1.019619889 2.33141441  1.86220601  1.551023075 1.601418379 2.002273876 0.957165881
75  1.853140166 7.098379135 1.182675991 2.322268357 1.813515351 1.615939602 1.696614356 2.035073751 0.958010381
80  1.798210945 2.222645814 0.969712319 2.240342429 1.913167003 1.668853612 1.697958527 2.093574065 0.957251029
85  1.800217051 6.402182459 0.860639426 2.246098499 1.907598223 1.682098292 1.745796169 2.121305706 0.954894171
90  1.803848201 1.837969653 1.102897318 2.129789813 2.043044807 1.735093642 1.666707881 2.129939238 0.950959419
95  1.773136099 1.81561362  1.063019374 2.101027448 2.068051192 1.741234984 1.560080567 2.035059171 0.945479261
100 1.726054688 2.336579799 1.191580262 2.171114687 2.000358256 1.941099801 1.344295317 2.148571187 0.938498408
105 1.732335377 1.525364359 0.997056804 2.22337609  1.992471357 1.947338911 1.29520691  2.118027771 0.924464116
110 1.712195122 2.147877272 1.236796081 2.19147367  1.98315409  1.971128342 1.406685721 2.150012062 0.894661016
115 1.850123948 1.655380701 1.182880578 2.193327785 1.89713277  1.98215189  1.291643391 2.11847296  1.056295377

-----------------我想要的---------

    x1      x2      x3      x4      x5      x6      x7      x8      x9  
1   1.847652137 1.593196753 1.038744382 2.392577214 1.993847864 2.06124419 1.320106097  2.029994348 1.214182727

# read in data
dat <- structure(list(x1 = c(2, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1), 
                      x2 = c(2, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1), 
                      x3 = c(1.1, 1.1, 3, 1.1, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2), 
                      x4 = c(2.4, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.6, 2.6, 2.6, 2.6, 2.6), 
                      x5 = c(2, 2.1, 2.2, 2.1, 2.1, 2.1, 2.2, 2.2, 2.2, 2.2, 2.2, 2.2), 
                      x6 = c(2.1, 2.2, 2.2, 2.3, 2.3, 2.3, 2.3, 2.3, 2.3, 2.3, 2.3, 2.4), 
                      x7 = c(1.4, 1.4, 1.4, 1.4, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5), 
                      x8 = c(2.2, 2.2, 2.2, 2.2, 2.2, 2.2, 2.2, 2.3, 2.3, 2.3, 2.3, 2.3), 
                      x9 = c(1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.4, 1.4, 1.4)), 
                 .Names = c("x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9"), 
                 class = "data.frame", 
                 row.names=c("5","10","15","20","25","30","35","40","45","50","55","60"))
# number of desired result rows
iterate = 3
# empty matrix to fill
RESULT <- matrix(NA, nrow = iterate, ncol = ncol(dat))

循环实际上是关于检查我们是否达到了目标,然后跟踪在第 i * 5 个约束的结果中已经捕获的内容,但是因为第 i 行将从 k 开始(迭代)我们不想为第一次检查开始做 3 * 5,所以我们做 which(i == k:n) 回到 1 * 5。

extract <- function(dat, iterate = 3, sum.increment = 5){
  dat <- as.matrix(dat)
  n <- nrow(dat)
  p <- ncol(dat)
  RESULT <- matrix(NA, nrow = iterate, ncol = p)
  for(k in 1:iterate){
    x <- 1  
    for(i in k:n){
      if(x == 1){
        hit <- which(cumsum(dat[i,]) > sum.increment)[1]
      } else {
        hit <- which(cumsum( # 
          c(RESULT[k,c(1:ifelse(hit>p,p,hit))], # keep track of previous values
            dat[i,-c(1:(x-1))]) # to cumulatively sum with new values
        ) > sum.increment * which(i == k:n))[1]
      }

      hit <- ifelse(is.na(hit) | hit > p, p, hit) # end of the matrix
      RESULT[k,c(x:hit)] <- unlist(dat[i,c(x:hit)])
      if(hit == p) break # if we're at the end of the cols, start the next iteration
      x <- hit + 1
    }
  }
  if(!is.null(colnames(dat))) colnames(RESULT) <- colnames(dat)
  return(RESULT)
}
extract(dat, iterate = 3, sum.increment = 5)

结果在这里

RESULT
#      x1  x2  x3  x4  x5  x6  x7  x8  x9
#[1,] 2.0 2.0 1.1 2.5 2.1 2.2 1.4 2.2 1.3
#[2,] 2.1 2.1 1.1 2.5 2.2 2.2 1.4 2.2 1.3
#[3,] 2.1 2.1 3.0 2.5 2.1 2.3 1.5 2.2 1.3