【问题标题】:Replace NAs with missing values in sequence (R)用序列中的缺失值替换 NA (R)
【发布时间】:2021-10-11 00:05:53
【问题描述】:

我有一个像这样的DF

现在我想将 Col B = NA 替换为 15,因为这是缺失值。 Col C 第一个 NA 为 14,第二个 NA 为 15。 Col D 第一个 NA 为 13,第二个 NA 为 14,第三个 NA 为 15。 所以数字遵循从上到下或从下到上的顺序。

可重现的样本数据

structure(list(`Col A` = c(11, 12, 13, 14, 15), `Col B` = c(NA, 
11, 12, 13, 14), `Col C` = c(NA, NA, 11, 12, 13), `Col D` = c(NA, 
NA, NA, 11, 12)), row.names = c(NA, -5L), class = c("tbl_df", 
"tbl", "data.frame"))

【问题讨论】:

    标签: r dataframe na imputation


    【解决方案1】:

    我认为您可以在tidyverse 中使用以下解决方案:

    library(dplyr)
    library(purrr)
    
    df[1] %>%
      bind_cols(map_dfc(2:length(df), function(x) {
        df[[x]][which(is.na(df[[x]]))] <- setdiff(df[[1]], df[[x]][!is.na(df[[x]])])
        df[x]
      }))
    
    # A tibble: 5 x 4
      `Col A` `Col B` `Col C` `Col D`
        <dbl>   <dbl>   <dbl>   <dbl>
    1      11      15      14      13
    2      12      11      15      14
    3      13      12      11      15
    4      14      13      12      11
    5      15      14      13      12
    

    或者在 base R 中我们可以这样做:

    do.call(cbind, Reduce(function(x, y) {
      i <- which(is.na(df[[y]]))
      df[[y]][i] <- sort(setdiff(x, df[[y]]))
      df[[y]]
    }, init = df[[1]], 2:length(df), accumulate = TRUE)) |>
      as.data.frame() |>
      setNames(paste0("Col", LETTERS[1:length(df)]))
    
      ColA ColB ColC ColD
    1   11   15   14   13
    2   12   11   15   14
    3   13   12   11   15
    4   14   13   12   11
    5   15   14   13   12
    

    【讨论】:

    • 绝妙的答案!亲爱的朋友
    【解决方案2】:

    你可以试试:

    df[is.na(df)] <- head({tm <- toeplitz(rev(df$ColA))}[upper.tri(tm, diag = TRUE)], sum(is.na(df)))
    

    这给出了:

      ColA ColB ColC ColD
    1   11   15   14   13
    2   12   11   15   14
    3   13   12   11   15
    4   14   13   12   11
    5   15   14   13   12
    

    【讨论】:

      【解决方案3】:

      试试下面的代码

      df[-1] <- lapply(
        df[-1],
        function(x) {
          replace(x, is.na(x), df[[1]][is.na(match(df[[1]], x))])
        }
      )
      

      你会得到

      > df
      # A tibble: 5 x 4
        `Col A` `Col B` `Col C` `Col D`
          <dbl>   <dbl>   <dbl>   <dbl>
      1      11      15      14      13
      2      12      11      15      14
      3      13      12      11      15
      4      14      13      12      11
      5      15      14      13      12
      

      【讨论】:

      • 真正优雅简洁。
      【解决方案4】:

      如果序列是恒定的(在这种情况下从 11 到 15),那么使用 dplyr 的一个选项可能是:

      df %>%
       mutate(across(everything(), ~ if_else(is.na(.), max(., na.rm = TRUE) + cumsum(is.na(.)), .)))
      
        `Col A` `Col B` `Col C` `Col D`
          <dbl>   <dbl>   <dbl>   <dbl>
      1      11      15      14      13
      2      12      11      15      14
      3      13      12      11      15
      4      14      13      12      11
      5      15      14      13      12
      

      如果顺序可能不同,那么一种选择可能是:

      df %>%
       mutate(across(-1, 
                     ~ if_else(is.na(.),
                               cumsum(is.na(.)) - 1 + last(pull(select(cur_data(), which(names(cur_data()) == cur_column()) - 1))),
                               .)))
      

      或者:

      df %>%
       mutate(across(-1, 
                     ~ if_else(is.na(.),
                               cumsum(is.na(.)) - 1 + last(get(paste0("Col ", LETTERS[which(names(cur_data()) == cur_column()) - 1]))),
                               .)))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-01-13
        • 1970-01-01
        • 1970-01-01
        • 2019-08-06
        • 2016-03-08
        • 2022-06-16
        • 2020-08-10
        • 2015-07-28
        相关资源
        最近更新 更多