【问题标题】:repeat loop has zero replacements重复循环的替换次数为零
【发布时间】:2017-07-14 18:27:30
【问题描述】:

我正在尝试编写一个循环,将组 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
}

【问题讨论】:

    标签: r loops repeat


    【解决方案1】:

    几个问题。一、在你说的文字中

    当循环遇到一个值大于的列时 对应的“中间”列值

    但在你的代码中,你有

    if(groups[i][[10]] &gt; 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]]
    }
    

    让我们打开它。该函数将从data.frame 传递一行x,在这种情况下,我假设groups data.frame。对于数据集中的第一行,x 将是 c(33, 55, 109, 114, 120, 169, 209, 214, 238, 119)。函数的第一行是检查 x 的除最后一个元素之外的任何值是否大于最后一个元素,如果不是则返回“no”。如果至少有一个值更大,则第二行将返回第一个值,并返回该列的相应名称。

    因此,对于groups 的第一行,我们希望函数返回“5”。

    现在,让apply 将函数添加到groups 的每一行。

    apply(groups, 1, appfunc)

    这里的语法很简单。这只是说将我们上面定义的appfunc 应用于groups 中的每一行。

    输出:

    # [1] "five"  "six"   "three" "four"  "six"   "three" "six"   "five"  "six"   "six" 
    

    【讨论】:

      【解决方案2】:

      我刚刚添加了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')) 
        }
      }
      

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

      【讨论】:

      • 我得到一个不同的错误: .subset2(x, i, exact = exact) 中的错误:下标越界。我必须打印什么吗?我可以跳过 else 语句,只为每一行打印真正的条件(中间 > 其他列)吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多