【问题标题】:How do I replace NA values with zeros in an R dataframe?如何在 R 数据框中用零替换 NA 值?
【发布时间】:2011-12-31 00:02:51
【问题描述】:

我有一个数据框,有些列有NA 值。

如何将这些 NA 值替换为零?

【问题讨论】:

标签: r dataframe na missing-data imputation


【解决方案1】:

对于单个向量:

x <- c(1,2,NA,4,5)
x[is.na(x)] <- 0

对于data.frame,从上面创建一个函数,然后apply它到列。

请在下次提供一个可重现的示例,如下所述:

How to make a great R reproducible example?

【讨论】:

  • is.na 是泛型函数,具有data.frame 类对象的方法。所以这个也适用于data.frames!
  • 当我第一次运行methods(is.na) 时,我就像whaaa?!?。我喜欢这样的事情发生! =)
  • 假设您有一个名为 df 的数据框而不是单个向量,并且您只想替换名为 X3 的单个列中的缺失观测值。您可以使用以下行来执行此操作: df$X3[is.na(df$X3)]
  • 假设您只想将名为 my.df 的数据框的第 4-6 列中的 NA 替换为 0。您可以使用:my.df[,4:6][is.na(my.df[,4:6])]
  • 你怎么把 'x' 传递给 is.na(x) 有没有办法知道 R 中的哪些库例程是矢量化的?
【解决方案2】:

在@gsk3 答案中查看我的评论。一个简单的例子:

> m <- matrix(sample(c(NA, 1:10), 100, replace = TRUE), 10)
> d <- as.data.frame(m)
   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1   4  3 NA  3  7  6  6 10  6   5
2   9  8  9  5 10 NA  2  1  7   2
3   1  1  6  3  6 NA  1  4  1   6
4  NA  4 NA  7 10  2 NA  4  1   8
5   1  2  4 NA  2  6  2  6  7   4
6  NA  3 NA NA 10  2  1 10  8   4
7   4  4  9 10  9  8  9  4 10  NA
8   5  8  3  2  1  4  5  9  4   7
9   3  9 10  1  9  9 10  5  3   3
10  4  2  2  5 NA  9  7  2  5   5

> d[is.na(d)] <- 0

> d
   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1   4  3  0  3  7  6  6 10  6   5
2   9  8  9  5 10  0  2  1  7   2
3   1  1  6  3  6  0  1  4  1   6
4   0  4  0  7 10  2  0  4  1   8
5   1  2  4  0  2  6  2  6  7   4
6   0  3  0  0 10  2  1 10  8   4
7   4  4  9 10  9  8  9  4 10   0
8   5  8  3  2  1  4  5  9  4   7
9   3  9 10  1  9  9 10  5  3   3
10  4  2  2  5  0  9  7  2  5   5

无需申请apply。 =)

编辑

您还应该看看norm 包。它有很多很好的缺失数据分析功能。 =)

【讨论】:

  • 我昨天在你发布之前已经尝试过这段代码,但没有成功。因为这个我发布了这个问题。但我试过知道并且工作得很好。我想我做错了什么。
  • @RenatoDinhaniConceição:如果您已经尝试过,那么在您提出问题时分享这些信息会很有帮助;它有助于缩小问题所在。
  • d[is.na(d)]
  • @user798719 - "
  • 并且...如果您有一个数据框并且只想将替换应用到特定的数字向量(例如...带有 NA 的字符串):df[19:28][is.na(df[19:28])] &lt;- 0
【解决方案3】:

您可以使用replace()

例如:

> x <- c(-1,0,1,0,NA,0,1,1)
> x1 <- replace(x,5,1)
> x1
[1] -1  0  1  0  1  0  1  1

> x1 <- replace(x,5,mean(x,na.rm=T))
> x1
[1] -1.00  0.00  1.00  0.00  0.29  0.00 1.00  1.00

【讨论】:

  • 正确,但仅当您知道向量中NAs 的索引时才实用。就像你的例子一样,对于小向量来说很好。
  • @dardisco x1 &lt;- replace(x,is.na(x),1) 无需明确列出索引值即可工作。
【解决方案4】:

如果我们在导出时尝试替换 NAs,例如写入 csv 时,那么我们可以使用:

  write.csv(data, "data.csv", na = "0")

【讨论】:

    【解决方案5】:

    dplyr 示例:

    library(dplyr)
    
    df1 <- df1 %>%
        mutate(myCol1 = if_else(is.na(myCol1), 0, myCol1))
    

    注意:这适用于每个选定的列,如果我们需要对所有列执行此操作,请参阅 @reidjax 使用 mutate_each 的答案。

    【讨论】:

      【解决方案6】:

      我知道问题已经得到解答,但这样做可能对某些人更有用:

      定义这个函数:

      na.zero <- function (x) {
          x[is.na(x)] <- 0
          return(x)
      }
      

      现在,当您需要将向量中的 NA 转换为零时,您可以这样做:

      na.zero(some.vector)
      

      【讨论】:

        【解决方案7】:

        在矩阵或向量中使用replace()NA 替换为0 的更一般的方法

        例如:

        > x <- c(1,2,NA,NA,1,1)
        > x1 <- replace(x,is.na(x),0)
        > x1
        [1] 1 2 0 0 1 1
        

        这也是在dplyr 中使用ifelse() 的替代方法

        df = data.frame(col = c(1,2,NA,NA,1,1))
        df <- df %>%
           mutate(col = replace(col,is.na(col),0))
        

        【讨论】:

        • 我的专栏是一个因素,所以我不得不添加我的重置价值levels(A$x) &lt;- append(levels(A$x), "notAnswered") A$x &lt;- replace(A$x,which(is.na(A$x)),"notAnswered")
        • which 这里不需要,你可以使用x1 &lt;- replace(x,is.na(x),1)
        • 我尝试了在这个线程中提出的许多方法来将 NA 替换为 0 在大型数据框中的一个特定列中,这个函数 replace() 工作得最有效,同时也最简单.
        【解决方案8】:

        如果您想替换因子变量中的 NA,这可能很有用:

        n <- length(levels(data.vector))+1
        
        data.vector <- as.numeric(data.vector)
        data.vector[is.na(data.vector)] <- n
        data.vector <- as.factor(data.vector)
        levels(data.vector) <- c("level1","level2",...,"leveln", "NAlevel") 
        

        它将因子向量转换为数字向量并添加另一个人工数字因子级别,然后将其转换回具有您选择的额外“NA 级别”的因子向量。

        【讨论】:

          【解决方案9】:

          会评论@ianmunoz 的帖子,但我没有足够的声誉。您可以结合dplyrmutate_eachreplace 来处理NA0 的替换。使用来自@aL3xa 答案的数据框...

          > m <- matrix(sample(c(NA, 1:10), 100, replace = TRUE), 10)
          > d <- as.data.frame(m)
          > d
          
              V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
          1   4  8  1  9  6  9 NA  8  9   8
          2   8  3  6  8  2  1 NA NA  6   3
          3   6  6  3 NA  2 NA NA  5  7   7
          4  10  6  1  1  7  9  1 10  3  10
          5  10  6  7 10 10  3  2  5  4   6
          6   2  4  1  5  7 NA NA  8  4   4
          7   7  2  3  1  4 10 NA  8  7   7
          8   9  5  8 10  5  3  5  8  3   2
          9   9  1  8  7  6  5 NA NA  6   7
          10  6 10  8  7  1  1  2  2  5   7
          
          > d %>% mutate_each( funs_( interp( ~replace(., is.na(.),0) ) ) )
          
              V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
          1   4  8  1  9  6  9  0  8  9   8
          2   8  3  6  8  2  1  0  0  6   3
          3   6  6  3  0  2  0  0  5  7   7
          4  10  6  1  1  7  9  1 10  3  10
          5  10  6  7 10 10  3  2  5  4   6
          6   2  4  1  5  7  0  0  8  4   4
          7   7  2  3  1  4 10  0  8  7   7
          8   9  5  8 10  5  3  5  8  3   2
          9   9  1  8  7  6  5  0  0  6   7
          10  6 10  8  7  1  1  2  2  5   7
          

          我们在这里使用标准评估 (SE),这就是为什么我们需要在“funs_”上加上下划线。我们还使用lazyevalinterp/~. 引用“我们正在使用的一切”,即数据框。现在有零了!

          【讨论】:

            【解决方案10】:

            使用dplyr 0.5.0,您可以使用coalesce 功能,通过coalesce(vec, 0) 可以轻松集成到%&gt;% 管道中。这会将vec 中的所有 NA 替换为 0:

            假设我们有一个带有NAs 的数据框:

            library(dplyr)
            df <- data.frame(v = c(1, 2, 3, NA, 5, 6, 8))
            
            df
            #    v
            # 1  1
            # 2  2
            # 3  3
            # 4 NA
            # 5  5
            # 6  6
            # 7  8
            
            df %>% mutate(v = coalesce(v, 0))
            #   v
            # 1 1
            # 2 2
            # 3 3
            # 4 0
            # 5 5
            # 6 6
            # 7 8
            

            【讨论】:

            • 我测试了coalesce,它的性能和replace差不多。到目前为止,coalesce 命令是最简单的!
            • 如果您能介绍如何将其应用于 2+ 列 tibble 的所有列,将会很有用。
            【解决方案11】:

            另一个dplyr 管道兼容选项与tidyrmethod replace_na 适用于多个列:

            require(dplyr)
            require(tidyr)
            
            m <- matrix(sample(c(NA, 1:10), 100, replace = TRUE), 10)
            d <- as.data.frame(m)
            
            myList <- setNames(lapply(vector("list", ncol(d)), function(x) x <- 0), names(d))
            
            df <- d %>% replace_na(myList)
            

            您可以轻松地限制为例如数字列:

            d$str <- c("string", NA)
            
            myList <- myList[sapply(d, is.numeric)]
            
            df <- d %>% replace_na(myList)
            

            【讨论】:

              【解决方案12】:

              另一个使用 imputeTS 包的例子:

              library(imputeTS)
              na.replace(yourDataframe, 0)
              

              【讨论】:

                【解决方案13】:

                dplyr 杂交选项现在比重新分配的 Base R 子集快约 30%。在 100M 数据点上,数据帧 mutate_all(~replace(., is.na(.), 0)) 的运行速度比基本 R d[is.na(d)] &lt;- 0 选项快半秒。想要特别避免的是使用ifelse()if_else()。 (完整的 600 次试验分析运行超过 4.5 小时,主要是因为包含了这些方法。)请参阅下面的基准分析以了解完整的结果。

                如果您在处理大量数据帧,data.table 是最快的选择:比标准 Base R 方法快 40%。它还可以就地修改数据,有效地让您一次处理几乎两倍的数据。


                其他有用的 tidyverse 替换方法的聚类

                地理位置:

                • 索引 mutate_at(c(5:10), ~replace(., is.na(.), 0))
                • 直接参考 mutate_at(vars(var5:var10), ~replace(., is.na(.), 0))
                • 固定匹配 mutate_at(vars(contains("1")), ~replace(., is.na(.), 0))
                  • 或代替contains(),试试ends_with(),starts_with()
                • 模式匹配 mutate_at(vars(matches("\\d{2}")), ~replace(., is.na(.), 0))

                有条件地:
                (只改变一种类型,不理会其他类型。)

                • 整数 mutate_if(is.integer, ~replace(., is.na(.), 0))
                • 数字 mutate_if(is.numeric, ~replace(., is.na(.), 0))
                • 字符串 mutate_if(is.character, ~replace(., is.na(.), 0))

                完整分析 -

                为 dplyr 0.8.0 更新:函数使用 purrr 格式 ~ 符号:替换已弃用的 funs() 参数。

                测试的方法:

                # Base R: 
                baseR.sbst.rssgn   <- function(x) { x[is.na(x)] <- 0; x }
                baseR.replace      <- function(x) { replace(x, is.na(x), 0) }
                baseR.for          <- function(x) { for(j in 1:ncol(x))
                    x[[j]][is.na(x[[j]])] = 0 }
                
                # tidyverse
                ## dplyr
                dplyr_if_else      <- function(x) { mutate_all(x, ~if_else(is.na(.), 0, .)) }
                dplyr_coalesce     <- function(x) { mutate_all(x, ~coalesce(., 0)) }
                
                ## tidyr
                tidyr_replace_na   <- function(x) { replace_na(x, as.list(setNames(rep(0, 10), as.list(c(paste0("var", 1:10)))))) }
                
                ## hybrid 
                hybrd.ifelse     <- function(x) { mutate_all(x, ~ifelse(is.na(.), 0, .)) }
                hybrd.replace_na <- function(x) { mutate_all(x, ~replace_na(., 0)) }
                hybrd.replace    <- function(x) { mutate_all(x, ~replace(., is.na(.), 0)) }
                hybrd.rplc_at.idx<- function(x) { mutate_at(x, c(1:10), ~replace(., is.na(.), 0)) }
                hybrd.rplc_at.nse<- function(x) { mutate_at(x, vars(var1:var10), ~replace(., is.na(.), 0)) }
                hybrd.rplc_at.stw<- function(x) { mutate_at(x, vars(starts_with("var")), ~replace(., is.na(.), 0)) }
                hybrd.rplc_at.ctn<- function(x) { mutate_at(x, vars(contains("var")), ~replace(., is.na(.), 0)) }
                hybrd.rplc_at.mtc<- function(x) { mutate_at(x, vars(matches("\\d+")), ~replace(., is.na(.), 0)) }
                hybrd.rplc_if    <- function(x) { mutate_if(x, is.numeric, ~replace(., is.na(.), 0)) }
                
                # data.table   
                library(data.table)
                DT.for.set.nms   <- function(x) { for (j in names(x))
                    set(x,which(is.na(x[[j]])),j,0) }
                DT.for.set.sqln  <- function(x) { for (j in seq_len(ncol(x)))
                    set(x,which(is.na(x[[j]])),j,0) }
                DT.nafill        <- function(x) { nafill(df, fill=0)}
                DT.setnafill     <- function(x) { setnafill(df, fill=0)}
                

                本次分析的代码:

                library(microbenchmark)
                # 20% NA filled dataframe of 10 Million rows and 10 columns
                set.seed(42) # to recreate the exact dataframe
                dfN <- as.data.frame(matrix(sample(c(NA, as.numeric(1:4)), 1e7*10, replace = TRUE),
                                            dimnames = list(NULL, paste0("var", 1:10)), 
                                            ncol = 10))
                # Running 600 trials with each replacement method 
                # (the functions are excecuted locally - so that the original dataframe remains unmodified in all cases)
                perf_results <- microbenchmark(
                    hybrid.ifelse    = hybrid.ifelse(copy(dfN)),
                    dplyr_if_else    = dplyr_if_else(copy(dfN)),
                    hybrd.replace_na = hybrd.replace_na(copy(dfN)),
                    baseR.sbst.rssgn = baseR.sbst.rssgn(copy(dfN)),
                    baseR.replace    = baseR.replace(copy(dfN)),
                    dplyr_coalesce   = dplyr_coalesce(copy(dfN)),
                    tidyr_replace_na = tidyr_replace_na(copy(dfN)),
                    hybrd.replace    = hybrd.replace(copy(dfN)),
                    hybrd.rplc_at.ctn= hybrd.rplc_at.ctn(copy(dfN)),
                    hybrd.rplc_at.nse= hybrd.rplc_at.nse(copy(dfN)),
                    baseR.for        = baseR.for(copy(dfN)),
                    hybrd.rplc_at.idx= hybrd.rplc_at.idx(copy(dfN)),
                    DT.for.set.nms   = DT.for.set.nms(copy(dfN)),
                    DT.for.set.sqln  = DT.for.set.sqln(copy(dfN)),
                    times = 600L
                )
                

                结果总结

                > print(perf_results)
                Unit: milliseconds
                              expr       min        lq     mean   median       uq      max neval
                      hybrd.ifelse 6171.0439 6339.7046 6425.221 6407.397 6496.992 7052.851   600
                     dplyr_if_else 3737.4954 3877.0983 3953.857 3946.024 4023.301 4539.428   600
                  hybrd.replace_na 1497.8653 1706.1119 1748.464 1745.282 1789.804 2127.166   600
                  baseR.sbst.rssgn 1480.5098 1686.1581 1730.006 1728.477 1772.951 2010.215   600
                     baseR.replace 1457.4016 1681.5583 1725.481 1722.069 1766.916 2089.627   600
                    dplyr_coalesce 1227.6150 1483.3520 1524.245 1519.454 1561.488 1996.859   600
                  tidyr_replace_na 1248.3292 1473.1707 1521.889 1520.108 1570.382 1995.768   600
                     hybrd.replace  913.1865 1197.3133 1233.336 1238.747 1276.141 1438.646   600
                 hybrd.rplc_at.ctn  916.9339 1192.9885 1224.733 1227.628 1268.644 1466.085   600
                 hybrd.rplc_at.nse  919.0270 1191.0541 1228.749 1228.635 1275.103 2882.040   600
                         baseR.for  869.3169 1180.8311 1216.958 1224.407 1264.737 1459.726   600
                 hybrd.rplc_at.idx  839.8915 1189.7465 1223.326 1228.329 1266.375 1565.794   600
                    DT.for.set.nms  761.6086  915.8166 1015.457 1001.772 1106.315 1363.044   600
                   DT.for.set.sqln  787.3535  918.8733 1017.812 1002.042 1122.474 1321.860   600
                

                结果箱线图

                ggplot(perf_results, aes(x=expr, y=time/10^9)) +
                    geom_boxplot() +
                    xlab('Expression') +
                    ylab('Elapsed Time (Seconds)') +
                    scale_y_continuous(breaks = seq(0,7,1)) +
                    coord_flip()
                

                颜色编码的试验散点图(y 轴在对数刻度上)

                qplot(y=time/10^9, data=perf_results, colour=expr) + 
                    labs(y = "log10 Scaled Elapsed Time per Trial (secs)", x = "Trial Number") +
                    coord_cartesian(ylim = c(0.75, 7.5)) +
                    scale_y_log10(breaks=c(0.75, 0.875, 1, 1.25, 1.5, 1.75, seq(2, 7.5)))
                

                关于其他高绩效者的说明

                当数据集变大时,Tidyrreplace_na 历来都排在前面。使用当前要运行的 100M 数据点集合,它的性能几乎与 Base R For 循环一样好。我很想知道不同大小的数据框会发生什么。

                mutatesummarize _at_all 函数变体的其他示例可在此处找到:https://rdrr.io/cran/dplyr/man/summarise_all.html 此外,我在这里找到了有用的演示和示例集合:https://blog.exploratory.io/dplyr-0-5-is-awesome-heres-why-be095fd4eb8a

                归因和感谢

                特别感谢:

                • Tyler RinkerAkrun 用于演示微基准测试。
                • alexis_laz 帮助我理解 local() 的使用,以及(在 Frank 的耐心帮助下)无声强制在加速其中许多方法中所起的作用。
                • ArthurYip 为您添加新的 coalesce() 函数并更新分析。
                • Gregor 推动了 data.table 函数的计算,最终将它们包含在阵容中。
                • Base R For 循环:alexis_laz
                • data.table For 循环:Matt_Dowle
                • Roman 解释了 is.numeric() 真正测试的内容。

                (当然,如果你觉得这些方法有用,也请过来给他们点赞。)

                关于我使用 Numerics 的注意事项:如果您确实有一个纯整数数据集,那么您的所有函数都会运行得更快。请参阅alexiz_laz's work 了解更多信息。 IRL,我不记得遇到过包含超过 10-15% 整数的数据集,所以我在全数字数据帧上运行这些测试。

                使用的硬件 3.9 GHz CPU 和 24 GB RAM

                【讨论】:

                • @Frank - 感谢您发现这种差异。参考文献都被清理干净了,结果已经完全在一台机器上重新运行并重新发布。
                • 好的,谢谢。还有,我觉得df1[j][is.na(df1[j])] = 0是错的,应该是df1[[j]][is.na(df1[[j]])] = 0
                • @UweBlock - 好问题:它允许我使用所有函数在完全相同的数据帧上进行子集左分配操作。由于我必须围绕该功能将本地包裹起来,所以以科学的名义 [一份工作,你有一份工作!] 我将它包裹在所有这些功能上,这样竞争环境就明确无误了。欲了解更多信息 - 请参阅此处:stackoverflow.com/questions/41604711/… 我已经精简了之前相当冗长的答案 - 但讨论的这一部分最好重新添加。谢谢!
                • @ArthurYip - 我添加了coalesce() 选项并一直重新运行。感谢您推动更新。
                • 对 dplyr 1.0.2 的更新删除了 mutate_atmutate_all: function(x) { mutate(across(x, ~replace_na(., 0))) }
                【解决方案14】:

                Datacamp 中提取的这个简单函数可能会有所帮助:

                replace_missings <- function(x, replacement) {
                  is_miss <- is.na(x)
                  x[is_miss] <- replacement
                
                  message(sum(is_miss), " missings replaced by the value ", replacement)
                  x
                }
                

                然后

                replace_missings(df, replacement = 0)
                

                【讨论】:

                  【解决方案15】:

                  也可以使用tidyr::replace_na

                      library(tidyr)
                      df <- df %>% mutate_all(funs(replace_na(.,0)))
                  

                  编辑(dplyr > 1.0.0):

                  df %>% mutate(across(everything(), .fns = ~replace_na(.,0))) 
                  

                  【讨论】:

                  • mutate_* 动词现在被across()取代
                  【解决方案16】:

                  nafillsetnafill 的专用函数在 data.table 中。 只要可用,它们就会在多个线程上分配要计算的列。

                  library(data.table)
                  
                  ans_df <- nafill(df, fill=0)
                  
                  # or even faster, in-place
                  setnafill(df, fill=0)
                  

                  【讨论】:

                  • 对于那些不赞成投票的人,也请提供反馈,以便我的回答可以改进。
                  【解决方案17】:

                  编写它的简单方法是使用来自hablarif_na

                  library(dplyr)
                  library(hablar)
                  
                  df <- tibble(a = c(1, 2, 3, NA, 5, 6, 8))
                  
                  df %>% 
                    mutate(a = if_na(a, 0))
                  

                  返回:

                        a
                    <dbl>
                  1     1
                  2     2
                  3     3
                  4     0
                  5     5
                  6     6
                  7     8
                  

                  【讨论】:

                    【解决方案18】:

                    如果您想在本例列 V3 中更改特定列中的 NA 后分配一个新名称,使用您也可以这样做

                    my.data.frame$the.new.column.name <- ifelse(is.na(my.data.frame$V3),0,1)
                    

                    【讨论】:

                      【解决方案19】:

                      要替换数据框中的所有 NA,您可以使用:

                      df %&gt;% replace(is.na(.), 0)

                      【讨论】:

                      • 这不是一个新的解决方案
                      【解决方案20】:

                      cleaner 包有一个na_replace() 泛型,默认情况下用零替换数值,用FALSE 替换逻辑,用今天替换日期等:

                      starwars %>% na_replace()
                      na_replace(starwars)
                      

                      它甚至支持向量化替换:

                      mtcars[1:6, c("mpg", "hp")] <- NA
                      na_replace(mtcars, mpg, hp, replacement = c(999, 123))
                      

                      文档:https://msberends.github.io/cleaner/reference/na_replace.html

                      【讨论】:

                        【解决方案21】:

                        我想添加一个使用流行的Hmisc package 的下一个解决方案。

                        library(Hmisc)
                        data(airquality)
                        # imputing with 0 - all columns
                        # although my favorite one for simple imputations is Hmisc::impute(x, "random")
                        > dd <- data.frame(Map(function(x) Hmisc::impute(x, 0), airquality))
                        > str(dd[[1]])
                         'impute' Named num [1:153] 41 36 12 18 0 28 23 19 8 0 ...
                         - attr(*, "names")= chr [1:153] "1" "2" "3" "4" ...
                         - attr(*, "imputed")= int [1:37] 5 10 25 26 27 32 33 34 35 36 ...
                        > dd[[1]][1:10]
                          1   2   3   4   5   6   7   8   9  10 
                         41  36  12  18  0*  28  23  19   8  0* 
                        

                        可以看出,所有的插补元数据都被分配为属性。所以以后可以用。

                        【讨论】:

                          【解决方案22】:

                          在data.frame中不需要通过mutate创建新列。

                          library(tidyverse)    
                          k <- c(1,2,80,NA,NA,51)
                          j <- c(NA,NA,3,31,12,NA)
                                  
                          df <- data.frame(k,j)%>%
                             replace_na(list(j=0))#convert only column j, for example
                              
                          

                          结果

                          k   j
                          1   0           
                          2   0           
                          80  3           
                          NA  31          
                          NA  12          
                          51  0   
                          

                          【讨论】:

                            【解决方案23】:

                            dplyr >= 1.0.0

                            在较新版本的dplyr

                            across() 取代了 summarise_at()、summarise_if() 和 summarise_all() 等“范围变体”系列。

                            df <- data.frame(a = c(LETTERS[1:3], NA), b = c(NA, 1:3))
                            
                            library(tidyverse)
                            
                            df %>% 
                              mutate(across(where(anyNA), ~ replace_na(., 0)))
                            
                              a b
                            1 A 0
                            2 B 1
                            3 C 2
                            4 0 3
                            

                            此代码将强制0 成为第一列中的字符。要根据列类型替换 NA,您可以在 where 中使用类似 purrr 的公式:

                            df %>% 
                              mutate(across(where(~ anyNA(.) & is.character(.)), ~ replace_na(., "0")))
                            

                            【讨论】:

                              【解决方案24】:

                              这并不是一个全新的解决方案,但我喜欢编写内联 lambdas 来处理我无法让包完成的事情。在这种情况下,

                              df %>%
                                 (function(x) { x[is.na(x)] <- 0; return(x) })
                              

                              因为 R 不会像您在 Python 中看到的那样“通过对象”,所以此解决方案不会修改原始变量 df,因此与大多数其他解决方案完全相同,但要少得多需要了解特定软件包的复杂知识。

                              注意函数定义周围的括号!虽然这对我来说似乎有点多余,但由于函数定义用花括号括起来,因此需要在 magrittr 的括号内定义内联函数。

                              【讨论】:

                                【解决方案25】:

                                无需使用任何库。

                                df <- data.frame(a=c(1,3,5,NA))
                                
                                df$a[is.na(df$a)] <- 0
                                
                                df
                                

                                【讨论】:

                                  【解决方案26】:

                                  替换数据框中的 is.na & NULL。

                                  1. 带列的数据框

                                  A$name[is.na(A$name)]

                                  A$name[is.na(A$name)]

                                  1. 包含所有数据框

                                  df[is.na(df)]

                                  1. 在数据框中将 na 替换为空白

                                  df[is.na(df)]

                                  1. 将 NULL 替换为 NA

                                  df[is.null(df)]

                                  【讨论】:

                                    猜你喜欢
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 2020-11-07
                                    • 1970-01-01
                                    • 2015-09-08
                                    • 2018-12-29
                                    • 1970-01-01
                                    • 2013-09-04
                                    相关资源
                                    最近更新 更多