如何在R数据框中将NA值替换为零?

961

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

我该如何用零替换这些NA值?


16
对 https://dev59.com/SGw05IYBdhLWcg3wXQwh 进行了小修改(我是通过搜索“[r] replace NA with zero”找到的)。 - Ben Bolker
@psychonomics,你的评论和最佳答案有什么区别? - user2110417
1
@svp - 可能什么都没有?我看不到我的评论。我是否已经删除了它,而你仍然可以查看? - psychonomics
30个回答

13

本人声望不够,无法评论 @ianmunoz 的帖子。可以结合 dplyrmutate_eachreplace 来处理 NA 替换为 0。使用来自 @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/~. 引用“我们正在处理的所有内容”,即数据框架。现在有了零!


12

使用 imputeTS 包的另一个示例:

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

11

data.table中有专门用于此目的的函数nafillsetnafill。如果可用,它们会将要在多个线程上计算的列进行分配。

library(data.table)

ans_df <- nafill(df, fill=0)

# or even faster, in-place
setnafill(df, fill=0)

11

如果您想替换因子变量中的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-级别”的因子向量。


8

无需使用任何库。

df <- data.frame(a=c(1,3,5,NA))

df$a[is.na(df$a)] <- 0

df

7

dplyr >= 1.0.0

在更新版本的dplyr中:

across()代替了"scoped variants"系列函数,如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")))

6
你可以使用 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

6
当你知道向量中NA的索引时,这种方法是可行的。对于像你示例中的小向量来说还不错。 - dardisco
5
x1 <- replace(x, is.na(x), 1) 可以在不显式列出索引值的情况下使用。 - lmo

6
“cleaner”包含一个“na_replace()”通用函数,它默认将数值替换为零,逻辑值替换为“FALSE”,日期替换为今天等。
library(dplyr)
library(cleaner)

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

4

另一个与dplyr管道兼容的选项,使用tidyr方法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)

3
一个简单的方法是使用来自 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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接