代码之家  ›  专栏  ›  技术社区  ›  Jordo82

不适用。仅当另一列未更改时发生locf

  •  0
  • Jordo82  · 技术社区  · 6 年前

    我为zoo::na创建了一些自定义调整。以前是locf,但这次我快发疯了。我需要一个函数,该函数将对列进行最后一次观察 只有 另一列中的值没有更改;所有这些都必须按主键分组。例如:

    library(dplyr)
    set.seed(20180409)
    
    data <- data.frame(Id = rep(1:10, each = 24),
                   Date = rep(seq.Date(as.Date("2016-01-01"), as.Date("2017-12-01"), 
                                       by = "month"), 10),
                   FillCol = replace(runif(240), runif(240) < 0.9, NA),
                   CheckCol = rep(letters[1:7], each = 7, length.out = 240))
    
    data <- data %>% 
      group_by(Id) %>% 
      mutate(CheckColHasChanged = replace(lag(CheckCol) != CheckCol, 
                                          is.na(lag(CheckCol) != CheckCol), TRUE),
             FillColIsNA = is.na(FillCol))
    

    因此,我试图对FillCol的任何观察结果进行前传,但一旦我们找到一个checkcol已更改的观察结果,请停止前传,直到FillCol中的下一个有效观察结果。我可以做一个循环,但我很难做到正确。

    Fill <- TRUE #indicator for whether or not I should be carrying forward
    for(row in 2:nrow(data)){
    
      #if the CheckCol has changed, don't fill
      if(data$CheckColHasChanged[row]){Fill <- FALSE}
    
      #if we should fill and still have the same Id, then fill from the last obs
      if(Fill & data$Id[row] == data$Id[row - 1]){
        data$FillCol[row] <- data$FillCol[row - 1]
      }else{ #if there's a valid obs in FillCol, set the indicator back to true
        if(!data$FillColIsNA[row]){Fill <- TRUE}
      }
    }
    

    任何帮助都将不胜感激!

    1 回复  |  直到 6 年前
        1
  •  1
  •   Gregor Thomas    6 年前

    回答注释:这只是通过Id和CheckCol填写:

    data %>% group_by(Id, CheckCol) %>% 
        mutate(result = zoo::na.locf(FillCol, na.rm = FALSE))
    

    你描述的方式 CheckCol ,它被视为ID。两者之间没有区别 “仅当另一列中的值未更改时” “按主键分组” 。您只有两列可供分组。