【问题标题】:Fill Column with 1 Until Value Found, Then Repeat Fill with 0 Until Value Found Again用 1 填充列直到找到值,然后用 0 重复填充直到再次找到值
【发布时间】:2022-01-12 07:00:24
【问题描述】:

我有以下数据框:

miniDF1 <- data.frame(Pred = c("A","A","B","A","B","B","C","A","B","C","A","A","A","A","B","A","C","B"))

    Pred
1     A
2     A
3     B
4     A
5     B
6     B
7     C
8     A
9     B
10    C
11    A
12    A
13    A
14    A
15    B
16    A
17    C
18    B

我正在尝试创建一个用 1 填充的新列,直到在 Pred 中找到“C”,然后用 0 填充新列,直到找到下一个“C”,并如此重复直到结束DF。我尝试了以下方法:

miniDF1 <- miniDF1 %>%
  mutate(Outcome = ifelse(str_detect(Pred, "C"), 1, 0)) %>% 
  fill(Outcome, .direction = 'up')

     Pred Outcome
1     A       0
2     A       0
3     B       0
4     A       0
5     B       0
6     B       0
7     C       1
8     A       0
9     B       0
10    C       1
11    A       0
12    A       0
13    A       0
14    A       0
15    B       0
16    A       0
17    C       1
18    B       0

但这只是将 1 放在有“C”所在的同一行中。

这是预期的样子:

miniDF2 <- data.frame(Pred = c("A","A","B","A","B","B","C","A","B","C","A","A","A","A","B","A","C","B"),
                     Outcome = c(1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,0))

     Pred Outcome
1     A       1
2     A       1
3     B       1
4     A       1
5     B       1
6     B       1
7     C       1
8     A       0
9     B       0
10    C       0
11    A       1
12    A       1
13    A       1
14    A       1
15    B       1
16    A       1
17    C       1
18    B       0

我不知道如何让值相应地翻转,但我认为这就是我的代码的 fill(Outcome, .direction = 'up') 部分的目的。

【问题讨论】:

    标签: r dplyr


    【解决方案1】:
    miniDF1$Outcome <- cumsum(c(1, head(miniDF1$Pred == 'C', -1))) %% 2
    
    miniDF1
       Pred Outcome
    1     A       1
    2     A       1
    3     B       1
    4     A       1
    5     B       1
    6     B       1
    7     C       1
    8     A       0
    9     B       0
    10    C       0
    11    A       1
    12    A       1
    13    A       1
    14    A       1
    15    B       1
    16    A       1
    17    C       1
    18    B       0
    

    在 tidyverse:

    library(dplyr)
    miniDF1 %>%
      mutate(Outcome = cumsum(lag(Pred == 'C', default = TRUE)) %% 2)
    

    【讨论】:

    • 在 tiydverse 示例中,您能解释一下%% 2 部分的作用吗?它代表Outcome 列中的01 吗?如果是%% 3,那么该列是否会被012 填充?
    • @samrizz4 是的,我将奇数改为 1,偶数改为 0
    • 我刚刚意识到%% 是模块化划分。谢谢!
    【解决方案2】:

    看起来很麻烦,但确实需要,

    i1 <- which(miniDF1$Pred == 'C')
    dd <- data.frame(v1 = c(1, 0),v2 = c(i1[1], abs(diff(i1)), nrow(miniDF1)-max(i1)))
    
    rep(dd$v1, dd$v2)
    #[1] 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 0
    

    也可以将其包装在一个函数中,

    fun1 <- function(x, val){
      i1 <- which(x == val)
      dd <- data.frame(v1 = c(1, 0),
                       v2 = c(i1[1], abs(diff(i1)), nrow(miniDF1)-max(i1)))
      return(rep(dd$v1, dd$v2))
    }
    
    miniDF1$outcome <- fun1(miniDF1$Pred, 'C')
    
    #   Pred outcome
    #1     A       1
    #2     A       1
    #3     B       1
    #4     A       1
    #5     B       1
    #6     B       1
    #7     C       1
    #8     A       0
    #9     B       0
    #10    C       0
    #11    A       1
    #12    A       1
    #13    A       1
    #14    A       1
    #15    B       1
    #16    A       1
    #17    C       1
    #18    B       0
    

    【讨论】:

      【解决方案3】:

      你可以试试rleidlike

      miniDF1$Outcome <- ifelse(data.table::rleid(miniDF1$Pred == "C") %% 4 %in% c(1,2), 1, 0)
      miniDF1
      
         Pred Outcome
      1     A       1
      2     A       1
      3     B       1
      4     A       1
      5     B       1
      6     B       1
      7     C       1
      8     A       0
      9     B       0
      10    C       0
      11    A       1
      12    A       1
      13    A       1
      14    A       1
      15    B       1
      16    A       1
      17    C       1
      18    B       0
      

      解释

      为了方便比较,我们试试miniDF1$x &lt;- rleid(miniDF1$Pred == "C")

         Pred Outcome x
      1     A       1 1
      2     A       1 1
      3     B       1 1
      4     A       1 1
      5     B       1 1
      6     B       1 1
      7     C       1 2
      8     A       0 3
      9     B       0 3
      10    C       0 4
      11    A       1 5
      12    A       1 5
      13    A       1 5
      14    A       1 5
      15    B       1 5
      16    A       1 5
      17    C       1 6
      18    B       0 7
      

      如果出现C 和下一个,您可以看到rleid 的结果发生变化。另外,当出现C 时,您需要从1 切换到0

      这意味着,如果x1 and 23 and 4 或...。需要有101 等等。所以我将 x 除以 4 并得到重复的 1 and 2/ 3 and 0 值。

      【讨论】:

      • 您能解释一下%% 4 %in% c(1,2) 部分的作用吗?我假设 c(1,2) 只是第一列和第二列,但不确定 4 的位置。
      • @samrizz4 我在上面添加了一些解释。我英语不好,所以可能没有帮助....如果您有任何其他问题,请告诉我。
      猜你喜欢
      • 2012-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-19
      相关资源
      最近更新 更多