重复循环没有替换

时间:2017-07-14 18:27:31

标签: r loops repeat

我正在尝试编写一个比较'中间'从DT / DF组到其前一列的值。当循环遇到一个值大于相应“中间”的列时。列值,将该列名称打印到名为mIncome的向量,并跳过其余列并继续循环中的下一次迭代。但是,循环似乎没有结束。

我最终想要一个包含第一列名称的向量,其值大于'中间'相应行的值。我知道循环不推荐,但如果有人有任何建议......

groups <- dput(groups)
structure(list(one = c(33, 32, 161, 93, 69, 74, 24, 24, 21, 25
), two = c(53, 68, 164, 111, 96, 125, 35, 103, 39, 25), three = c(109, 
97, 188, 159, 160, 169, 53, 149, 106, 34), four = c(114, 161, 
214, 183, 302, 190, 86, 193, 155, 62), five = c(120, 183, 237, 
241, 384, 257, 105, 388, 174, 62), six = c(169, 269, 264, 262, 
633, 293, 195, 489, 239, 122), seven = c(209, 351, 351, 279, 
717, 326, 243, 652, 291, 152), eight = c(214, 393, 357, 346, 
769, 336, 255, 672, 353, 197), nine = c(238, 459, 365, 364, 816, 
336, 336, 722, 363, 197), middle = c(119, 230, 182, 182, 408, 
168, 168, 361, 182, 98)), .Names = c("one", "two", "three", "four", 
"five", "six", "seven", "eight", "nine", "middle"), class = c("data.table", 
"data.frame"), row.names = c(NA, -10L), .internal.selfref = <pointer: 0x00000000000b0788>)




repeat{
   mIncome <- character(length = nrow(groups))

for(i in 1:(dim(groups)[1])){
   for(j in 1:(dim(groups)[2] - 1)){
      if(groups[i][[10]] < groups[i][[j]]){ # is middle value greater than...
         mIncome[i] <- as.character(colnames(groups[, j - 1, with = FALSE]))
         break
         } else (print('no')) 
      } 
    }
   mIncome
}

2 个答案:

答案 0 :(得分:1)

我刚刚添加medclass[,j,with=FALSE],这应该可以解决您的问题。这是一个解决方案

for(i in 1:(dim(medclass)[1])){
  for(j in 1:(dim(medclass)[2] - 1)){
    if(groups[i][[10]] > groups[i][[j]]){ # is middle value greater than...
      mIncome[i] <- as.character(colnames(medclass[, j,with=FALSE]))
      next
    } else (print('no')) 
  }
}

具有正确索引的解决方案:

for(i in 1:(dim(medclass)[1])){
  for(j in 1:(dim(medclass)[2] - 3)){
    if(groups[i][[10]] > groups[i][[j]]){ # is middle value greater than...
      mIncome[i] <- as.character(colnames(medclass[, j+4,with=FALSE]))
      next
    } else (print('no')) 
  }
}

绝不是一个有效的解决方案。必须有一个有效的解决方案。

答案 1 :(得分:1)

一些问题。一,在你说的文字中

  

当循环遇到值大于的列时   相应的中间&#39;列值

但在您的代码中,您有

if(groups[i][[10]] > groups[i][[j]]){ # is middle value greater than...

那么,你想要的值大于中间值,或者中间值大于值吗?

其次,当您发现自己使用多个嵌套for循环时,可能有一种更简单的方法。

我将首先制作一个函数,然后将其应用于每一行。

appfunc <- function(x) {
  if (!any(x[1:(length(x)-1)] > x[length(x)])) return("no")
  names(groups)[which(x[1:(length(x)-1)] > x[length(x)])[1]]
}

让我们打开它。该函数将从x的{​​{1}}行传递,在这种情况下,我假设data.frame groups。对于数据集中的第一行,x将为data.frame。函数的第一行是检查除最后​​一个元素之外的x的任何值是否大于最后一个元素,如果不是,则返回&#34; no&#34;。如果至少有一个值更大,则第二行将返回第一行,并返回该列的相应名称。

因此,对于c(33, 55, 109, 114, 120, 169, 209, 214, 238, 119)中的第一行,我们希望函数返回&#34;五&#34;。

现在,让groups的每一行都有apply函数。

groups

这里的语法非常简单。这只是说将上面定义的apply(groups, 1, appfunc)应用于appfunc中的每一行。

输出:

groups