迭代地和分层地循环遍历行直到满足条件

Tho*_*del 9 loops r data-manipulation dplyr tidyr

我正在尝试解决R中的数据管理问题.

假设我的数据如下:

id <- c("123", "414", "606")
next.up <- c("414", "606", "119")
is.cond.met <- as.factor(c("FALSE", "FALSE", "TRUE"))
df <- data.frame(id, next.up, is.cond.met)

> df
   id next.up is.cond.met
1 123     414       FALSE
2 414     606       FALSE
3 606     119        TRUE
Run Code Online (Sandbox Code Playgroud)


我想获得的是以下内容:

id <- c("123", "414", "606")
next.up <- c("414", "606", "119")
is.cond.met <- as.factor(c("FALSE", "FALSE", "TRUE"))
origin <- c("606", "606", "119")
df.result <- data.frame(id, next.up, is.cond.met, origin)

> df.result
   id next.up is.cond.met origin
1 123     414       FALSE    606
2 414     606       FALSE    606
3 606     119        TRUE    119
Run Code Online (Sandbox Code Playgroud)


换句话说:当给定条件(is.met)为真时,我想将每个ID与其"原点"匹配.我遇到的困难是这是迭代和分层的:找到原点我可能需要经历多个分离度.逻辑步骤如下所示.我真的不确定如何解决这个问题.

逻辑步骤


更新
其中一条评论提出了一种适用于排序数据的data.frame解决方案,如上面的最小示例所示.实际上,我的数据没有以这种方式排序.一个更好的例子如下:

id <- c("961980", "14788", "902460", "900748", "728912", "141726", "1041190", "692268")
next.up <- c("20090", "655036", "40375164", "40031850", "40368996", "961980", "141726", "760112")
is.cond.met <- c(TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE)
df <- data.frame(id, next.up, is.cond.met, stringsAsFactors = FALSE)

glimpse(df)

Observations: 8
Variables: 3
$ id          <chr> "961980", "14788", "902460", "900748", "728912", "141726", "1041190", "692268"
$ next.up     <chr> "20090", "655036", "40375164", "40031850", "40368996", "961980", "141726", "760112"
$ is.cond.met <lgl> TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE
> df
       id  next.up is.cond.met
1  961980    20090        TRUE
2   14788   655036       FALSE
3  902460 40375164       FALSE
4  900748 40031850       FALSE
5  728912 40368996       FALSE
6  141726   961980       FALSE
7 1041190   141726       FALSE
8  692268   760112       FALSE
Run Code Online (Sandbox Code Playgroud)


更新2:最终结果应如下所示:

> df.end.result
       id  next.up is.cond.met origin
1  961980    20090        TRUE   <NA>
2   14788   655036       FALSE   <NA>
3  902460 40375164       FALSE   <NA>
4  900748 40031850       FALSE   <NA>
5  728912 40368996       FALSE   <NA>
6  141726   961980       FALSE 961980
7 1041190   141726       FALSE 961980
8  692268   760112       FALSE   <NA>
Run Code Online (Sandbox Code Playgroud)

Jaa*_*aap 5

我已经扩展了您的示例数据,以显示更多TRUE值的内容is.cond.met.使用该data.table包,您可以:

library(data.table)
setDT(df)[, grp := shift(cumsum(is.cond.met), fill=0)
          ][, origin := ifelse(is.cond.met, next.up, id[.N]), by = grp][]
Run Code Online (Sandbox Code Playgroud)

这使:

> df
    id next.up is.cond.met grp origin
1: 123     414       FALSE   0    606
2: 414     606       FALSE   0    606
3: 606     119        TRUE   0    119
4: 119     321       FALSE   1    321
5: 321     507        TRUE   1    507
6: 507     185        TRUE   2    185
Run Code Online (Sandbox Code Playgroud)

说明:

  1. 首先使用创建分组变量shift(cumsum(is.cond.met), fill=0).
  2. ifelse(is.cond.met, next.up, id[.N])您分配正确的值origin.

注意:idnext.up列应类字符的用于上述工作(由于这个原因我用stringsAsFactors = FALSE在构建扩展的例子的数据).如果它们是因素,请先将它们转换为as.character.如果is.cond.met还不合逻辑,请将其转换为as.logical.


在更新的示例数据上,上面的代码给出:

        id  next.up is.cond.met grp origin
1:  961980    20090        TRUE   0  20090
2:   14788   655036       FALSE   1 692268
3:  902460 40375164       FALSE   1 692268
4:  900748 40031850       FALSE   1 692268
5:  728912 40368996       FALSE   1 692268
6:  141726   961980       FALSE   1 692268
7: 1041190   141726       FALSE   1 692268
8:  692268   760112       FALSE   1 692268
Run Code Online (Sandbox Code Playgroud)

使用数据:

id <- c("123", "414", "606", "119", "321", "507")
next.up <- c("414", "606", "119", "321", "507", "185")
is.cond.met <- c(FALSE, FALSE, TRUE, FALSE, TRUE, TRUE)

df <- data.frame(id, next.up, is.cond.met, stringsAsFactors = FALSE)
Run Code Online (Sandbox Code Playgroud)