【问题标题】:Replace missing values with previous value for multiple columns by grouping通过分组将缺失值替换为多列的先前值
【发布时间】:2023-04-06 09:35:01
【问题描述】:

我有一个包含 6 个变量的数据框。对于每一列,同一组的数据相同,但有一些缺失值。我想通过为每个变量复制同一组的值来填充这些缺失值。如果特定组的所有值都缺失,则应填写上述组的值。所以,我希望结果为 df_complete。

这是我尝试过的方法,但是当缺少对任何组的第一次观察时它会失败。无法弄清楚其中有什么问题。

set.seed(123)
df <- data.frame(matrix(rnorm(100), ncol = 5))
df$Group <- letters[1:20]
df <- df[rep(seq_len(nrow(df)), sample(1:10, 20, replace = T)),]
df_complete <- df
df$X1[sample(1:nrow(df), 15)] <- NA
df$X2[sample(1:nrow(df), 10)] <- NA
df$X3[sample(1:nrow(df), 25)] <- NA
df$X4[sample(1:nrow(df), 10)] <- NA
df$X5[sample(1:nrow(df), 15)] <- NA

lvcf <- function(x)
{
  miss_ind <- which(is.na(x))

  if(length(miss_ind) != 0)
  {
    if(miss_ind[1]==1)
    {
      ind1 <- which(!is.na(x))[1]
      x[1] <- x[ind1]
      miss_ind <- which(is.na(x))
    }

    for(i in 1:length(miss_ind))
    {
      x[miss_ind[i]] <- x[miss_ind[i]-1]
    }
  }      
  return(x)
}

df_complete <- df %>%
  group_by(Group) %>%
  sapply(lvcf)

【问题讨论】:

    标签: r dplyr missing-data


    【解决方案1】:

    zoo 具有处理此类问题的功能,na.locf,用于last observation carried forward

    library(zoo)
    df_complete <- df %>%
      group_by(Group) %>%
      na.locf(., na.rm = FALSE)
    
    head(df_complete)
    ## A tibble: 6 x 6
    ## Groups:   Group [2]
    #           X1          X2          X3          X4           X5 Group
    #        <chr>       <chr>       <chr>       <chr>        <chr> <chr>
    #1 -0.56047565 -1.06782371 -0.69470698        <NA>  0.005764186     a
    #2 -0.56047565 -1.06782371 -0.69470698  0.37963948  0.005764186     a
    #3 -0.56047565 -1.06782371 -0.69470698  0.37963948  0.005764186     a
    #4 -0.23017749 -0.21797491 -0.20791728 -0.50232345  0.385280401     b
    #5 -0.23017749 -0.21797491 -0.20791728 -0.50232345  0.385280401     b
    #6 -0.23017749 -0.21797491 -0.20791728 -0.50232345  0.385280401     b
    

    注意X4 列中的&lt;NA&gt;

    编辑。
    在下面的 OP 评论和 G. Grothendieck 的回答之后,以下内容将删除所有 NA 值。只需使用第二个 na.locf 和参数 fromLast = TRUE

    df_complete <- df %>%
      group_by(Group) %>%
      na.locf(., na.rm = FALSE) %>%
      na.locf(., fromLast = TRUE)
    
    head(df_complete)
    ## A tibble: 6 x 6
    ## Groups:   Group [2]
    #           X1          X2          X3          X4           X5 Group
    #        <chr>       <chr>       <chr>       <chr>        <chr> <chr>
    #1 -0.56047565 -1.06782371 -0.69470698  0.37963948  0.005764186     a
    #2 -0.56047565 -1.06782371 -0.69470698  0.37963948  0.005764186     a
    #3 -0.56047565 -1.06782371 -0.69470698  0.37963948  0.005764186     a
    #4 -0.23017749 -0.21797491 -0.20791728 -0.50232345  0.385280401     b
    #5 -0.23017749 -0.21797491 -0.20791728 -0.50232345  0.385280401     b
    #6 -0.23017749 -0.21797491 -0.20791728 -0.50232345  0.385280401     b
    

    编辑 2
    根据 OP 发现的错误,这里有一个仅使用 base R 的解决方案。我将使用NA 值创建一个新的df,从每个组开始,但第一个组,即a 组。

    set.seed(123)
    
    df2 <- data.frame(X1 = rnorm(20),
                      X2 = rnorm(20),
                      Group = rep(letters[1:4], each = 5))
    df2[c(6, 11, 16), 1:2] <- NA
    
    df2_complete <- lapply(split(df2, df2$Group), function(x){
            k <- which(names(x) == "Group")
            x[-k] <- sapply(x[-k], na.locf, na.rm = FALSE)
            x[-k] <- sapply(x[-k], na.locf, fromLast = TRUE)
            x
    })
    df2_complete <- do.call(rbind, df2_complete)
    row.names(df2_complete) <- NULL
    df2_complete
    

    【讨论】:

    • 这就是为什么我制作了自定义函数,其中第一行的 NA 将被下一个可用值替换。
    • @Rajan,您可以使用na.fill(na.locf0(x), "extend") 扩展末尾的系列,也可以双向运行 na.locf:na.locf(na.locf0(x), fromLast = TRUE) `
    • @Grothendieck,它仍然不能解决我的问题。当 NA 出现在任何组的第一次观察中时,它正在替换前一组而不是该组的值。例如如果在第 b 组的第一次观察中缺少 X2 的值,即第 4 行,则将其替换为组 a 的值。这与我在代码中遇到的问题相同。
    • @Rajan 我的编辑不能解决问题吗?我看到第一个 NA 被同一组的下一个非缺失值替换。
    • @Rui,它确实替换了第一组,即 a,但对于其他组,它正在填充前一组的值。
    猜你喜欢
    • 2019-08-15
    • 2019-05-12
    • 2023-01-13
    • 1970-01-01
    • 1970-01-01
    • 2018-12-05
    • 1970-01-01
    • 2019-05-05
    • 1970-01-01
    相关资源
    最近更新 更多