【问题标题】:Loop Index automatically updated in the middle of Iteration循环索引在迭代过程中自动更新
【发布时间】:2018-01-13 09:51:18
【问题描述】:

请看一下这个简单的数据框:

1 4 a 2 5 b 3 6 c 4 7 d 5 8 e 6 9 f 7 10 g

暂时忽略第三列。我想创建一个带有二进制变量的第四列,该变量表示特定行是前一行的延续。

让我举例说明,

1 4 a 1 2 5 b 0 3 6 c 0 4 7 d 1 5 8 e 0 6 9 f 0 7 10 g 1

第一行我们从“1 到 4”开始,这是我们的基础,路径的起点。 在下一行我们有“2 到 5”,但由于我们已经在 4,所以数字 2 不是延续,所以,第四列得到一个“0”。这一行与我们的基地断开连接。 在下一行“3 到 6”中,再次断开连接,因为我们已经在 4,我们应该在 4 处重新开始。

这正是接下来发生的事情……“4 到 7”与第一行相连,因此第四列得到“1”。 同样,只有“7 到 10”行重新连接路径并获得“1”

最终我想过滤“1s”,因为字母列包含重要信息。但这很容易使用 dplyr。算了。

我失败的方法是这样的:我用 i 和 j 创建了一个循环,它将搜索第 2 列中的值何时等于第 1 列中的值,再往下。问题是,例如“2 到 5”行也与“5 到 8”行连接,并且会收到“1”

我看不到如何指示循环在找到第一个连接时“4 到 7”将该结果用作新的基础。只有这样,下一个正回报就是以 7 开头的行。

我的头好痛。我希望头脑冷静的人能给我指点光明。

谢谢大家。

【问题讨论】:

    标签: r loops for-loop foreach while-loop


    【解决方案1】:

    首先是您的数据集示例:

    dat <-
    structure(list(X = 1:7, Y = 4:10, Z = c("a", "b", "c", "d", "e", 
    "f", "g")), .Names = c("X", "Y", "Z"), class = "data.frame", row.names = c(NA, 
    -7L))
    

    现在试试下面的。

    next_one <- function(dat, curr){
        # Get the connect point from the second column
        i <- dat[curr, 2]
        # Now a vector of potential continuations
        i <- which(dat[, 1] >= i)
        # If there's a continuation, it's the first,
        #   else we're at the end of the column
        i <- if(length(i) >= 1) i[1] else 0L
        i
    }
    
    W <- integer(nrow(dat))
    W[1] <- 1L
    curr <- 1
    
    while(curr <= nrow(dat)){
        i <- next_one(dat, curr)
        if(i){
            W[i] <- 1L
            curr <- i
        }else
            break
    }
    
    new_dat <- cbind(dat, W)
    new_dat
      X  Y Z W
    1 1  4 a 1
    2 2  5 b 0
    3 3  6 c 0
    4 4  7 d 1
    5 5  8 e 0
    6 6  9 f 0
    7 7 10 g 1
    

    【讨论】:

    • David 的回答稍微简单一些,让测试原始数据的用途更加广泛。尽管如此,从长远来看,我还是在这方面,所以我很感谢您的解决方案。我将仔细研究您的代码,以表达对您的努力的感激之情,同时也为我的知识增加一个技巧。也许您可以解释一下“next_one”功能是如何工作的。它似乎比基本教程更高级。顺便说一句,我无法为您的答案投票,因为我没有足够的声望点。
    • @RandomLuck 不要担心选票,他们不会给我孙子留下深刻印象。至于函数如何工作的解释,我将编辑我的代码并包含 cmets。
    【解决方案2】:

    在 R 中使用简单循环的另一种尝试是:

    x <- 1:7
    y <- 4:10
    
    largest_nr <- min(x, y) # to get a 1 in the first entry
    res_vec <- c() # empty vector
    
    # loop through the numbers and check if we have a new largest number
    for (i in 1:length(x)) {
     if (min(x[i], y[i]) >= largest_nr) {
      # new largest number found
      largest_nr <- max(x[i], y[i])
      res_vec <- c(res_vec, 1)
     } else {
      # no new largest number found
      res_vec <- c(res_vec, 0)
     }
    }
    
    cbind(x, y, res_vec)
    #>      x  y res_vec
    #> [1,] 1  4       1
    #> [2,] 2  5       0
    #> [3,] 3  6       0
    #> [4,] 4  7       1
    #> [5,] 5  8       0
    #> [6,] 6  9       0
    #> [7,] 7 10       1
    

    【讨论】:

      猜你喜欢
      • 2019-07-28
      • 2020-08-07
      • 1970-01-01
      • 2018-06-18
      • 1970-01-01
      • 2021-10-08
      • 1970-01-01
      • 2013-01-03
      • 2013-04-29
      相关资源
      最近更新 更多