【问题标题】:R Replace NA for all Columns Except *R 替换除 * 之外的所有列的 NA
【发布时间】:2020-05-01 14:02:37
【问题描述】:
library(tidyverse)
df <- tibble(Date = c(rep(as.Date("2020-01-01"), 3), NA),
             col1 = 1:4,
             thisCol = c(NA, 8, NA, 3),
             thatCol = 25:28,
             col999 = rep(99, 4))
#> # A tibble: 4 x 5
#>   Date        col1  thisCol thatCol col999
#>   <date>     <int>    <dbl>   <int>  <dbl>
#> 1 2020-01-01     1       NA      25     99
#> 2 2020-01-01     2        8      26     99
#> 3 2020-01-01     3       NA      27     99
#> 4 NA             4        3      28     99

我的实际 R 数据框有数百列名称不整齐,但可以用上面的 df 数据框近似。

我想用0 替换NA 的所有值,除了几列(在我的示例中,我想省略Date 列和thatCol 列。我想以这种方式进行:

df %>% replace(is.na(.), 0)
#> Error: Assigned data `values` must be compatible with existing data.
#> i Error occurred for column `Date`.
#> x Can't convert <double> to <date>.
#> Run `rlang::last_error()` to see where the error occurred.

我完成“除此之外的所有”替换 NA 的不成功想法如下所示。

df %>% replace(is.na(c(., -c(Date, thatCol)), 0))
df %>% replace_na(list([, c(2:3, 5)] = 0))
df %>% replace_na(list(everything(-c(Date, thatCol)) = 0))

有没有办法以我需要的方式选择所有内容?有数百列,名称不一致,因此逐一键入它们是不切实际的选择。

【问题讨论】:

    标签: r select tidyr tidyselect


    【解决方案1】:

    你可以使用mutate_at

    library(dplyr)
    

    按名称删除它们

    df %>% mutate_at(vars(-c(Date, thatCol)), ~replace(., is.na(.), 0))
    

    按位置删除它们

    df %>% mutate_at(-c(1,4), ~replace(., is.na(.), 0))
    

    按名称选择它们

    df %>% mutate_at(vars(col1, thisCol, col999), ~replace(., is.na(.), 0))
    

    按位置选择它们

    df %>% mutate_at(c(2, 3, 5), ~replace(., is.na(.), 0))
    

    如果你想使用replace_na

    df %>% mutate_at(vars(-c(Date, thatCol)), tidyr::replace_na, 0)
    

    请注意,mutate_at 很快将被dplyr 1.0.0 中的across 取代。

    【讨论】:

      【解决方案2】:

      基于data.table,您有几个选项here

      最酷的选项之一:setnafill(版本 >= 1.12.4):

      library(data.table)
      setDT(df)
      
      data.table::setnafill(df,fill = 0, cols = colnames(df)[!(colnames(df) %in% c("Date", thatCol)]))
      

      请注意,您的数据框是通过引用更新的。

      【讨论】:

        【解决方案3】:

        另一个base解决方案:

         to_change<-grep("^(this|col)",names(df))
           df[to_change]<- sapply(df[to_change],function(x) replace(x,is.na(x),0))
            df
            # A tibble: 4 x 5
              Date        col1 thisCol thatCol col999
              <date>     <dbl>   <dbl>   <int>  <dbl>
            1 2020-01-01     1       0      25     99
            2 2020-01-01     2       8      26     99
            3 2020-01-01     3       0      27     99
            4 NA             0       3      28     99
        

        数据(我改变了一个值):

        df <- structure(list(Date = structure(c(18262, 18262, 18262, NA), class = "Date"), 
            col1 = c(1L, 2L, 3L, NA), thisCol = c(NA, 8, NA, 3), thatCol = 25:28, 
            col999 = c(99, 99, 99, 99)), row.names = c(NA, -4L), class = c("tbl_df", 
        "tbl", "data.frame"))
        

        【讨论】:

          【解决方案4】:

          replace 在 data.frame 上工作,所以我们可以通过索引替换并更新原始数据集

          df[-c(1, 4)] <- replace(df[-c(1, 4)], is.na(df[-c(1, 4)]), 0)
          

          或使用replace_naacross(来自新的dplyr

          library(dplyr)
          library(tidyr)
          df %>% 
               mutate(across(-c(Date, thatCol), ~ replace_na(., 0)))
          

          【讨论】:

            【解决方案5】:

            如果您知道不想更改的内容,您可以这样做:

            df <- tibble(Date = c(rep(as.Date("2020-01-01"), 3), NA),
                         col1 = 1:4,
                         thisCol = c(NA, 8, NA, 3),
                         thatCol = 25:28,
                         col999 = rep(99, 4))
            
            
            #dplyr
            df_nonreplace <- select(df, c("Date", "thatCol"))
            
            df_replace <- df[ ,!names(df) %in% names(df_nonreplace)]
            
            df_replace[is.na(df_replace)] <- 0
            
            df <- cbind(df_nonreplace, df_replace)
            
            
            > head(df)
                    Date thatCol col1 thisCol col999
            1 2020-01-01      25    1       0     99
            2 2020-01-01      26    2       8     99
            3 2020-01-01      27    3       0     99
            4       <NA>      28    4       3     99
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-11-05
              • 2022-01-16
              • 2020-07-22
              • 1970-01-01
              • 1970-01-01
              • 2019-11-05
              • 2011-11-08
              相关资源
              最近更新 更多