我有一个数据框,其中一些列具有NA
值。
我该如何用零替换这些NA
值?
这个简单的函数从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)
替换数据框中的is.na和NULL。
A $ name [is.na(A $ name)] <- 0
或
A $ name [is.na(A $ name)] <- "NA"
df [is.na(df)] <- 0
df [is.na(df)] <-“”
df [is.null(df)] <- NA
collapse::replace_NA
。默认情况下,replace_NA
会用0替换 NAs。library(collapse)
replace_NA(df)
只针对某些列:
replace_NA(df, cols = c("V1", "V5"))
#Alternatively, one can use a function, indices or a logical vector to select the 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))
microbenchmark(collapse = replace_NA(dfN))
# Unit: milliseconds
# expr min lq mean median uq max neval
# collapse 508.9198 621.405 751.3413 714.835 859.5437 1298.69 100
我想添加一个新的解决方案,使用一个流行的Hmisc
包。
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*
可以看到,所有的输入元数据都被分配为属性。因此以后可以使用它们。
另一种选项是使用sapply
将所有的NA
替换为零。以下是一些可重现的代码(数据来自@aL3xa):
set.seed(7) # for reproducibility
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 9 7 5 5 7 7 4 6 6 7
#> 2 2 5 10 7 8 9 8 8 1 8
#> 3 6 7 4 10 4 9 6 8 NA 10
#> 4 1 10 3 7 5 7 7 7 NA 8
#> 5 9 9 10 NA 7 10 1 5 NA 5
#> 6 5 2 5 10 8 1 1 5 10 3
#> 7 7 3 9 3 1 6 7 3 1 10
#> 8 7 7 6 8 4 4 5 NA 8 7
#> 9 2 1 1 2 7 5 9 10 9 3
#> 10 7 5 3 4 9 2 7 6 NA 5
d[sapply(d, \(x) is.na(x))] <- 0
d
#> V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
#> 1 9 7 5 5 7 7 4 6 6 7
#> 2 2 5 10 7 8 9 8 8 1 8
#> 3 6 7 4 10 4 9 6 8 0 10
#> 4 1 10 3 7 5 7 7 7 0 8
#> 5 9 9 10 0 7 10 1 5 0 5
#> 6 5 2 5 10 8 1 1 5 10 3
#> 7 7 3 9 3 1 6 7 3 1 10
#> 8 7 7 6 8 4 4 5 0 8 7
#> 9 2 1 1 2 7 5 9 10 9 3
#> 10 7 5 3 4 9 2 7 6 0 5
2023年1月15日创建,使用reprex v2.0.2生成。
\(x)
替代 function(x)
。这并不是一个全新的解决方案,但我喜欢编写内联lambda函数来处理那些我无法通过包来完成的事情。在这种情况下,
df %>%
(function(x) { x[is.na(x)] <- 0; return(x) })
因为 R 不像 Python 一样“按对象传递”,所以这个解决方案不会修改原始变量 df
,因此与大多数其他解决方案相比,需要的特定包的复杂知识要少得多。
请注意函数定义周围的括号!虽然对我来说似乎有点多余,因为函数定义被花括号包围,但是内联函数必须在括号中定义,以便使用 magrittr
。
这是一种更灵活的解决方案。它适用于您的数据框有多大,或者使用0
、zero
或任何其他表示零的方式。
library(dplyr) # make sure dplyr ver is >= 1.00
df %>%
mutate(across(everything(), na_if, 0)) # if 0 is indicated by `zero` then replace `0` with `zero`
my.data.frame$the.new.column.name <- ifelse(is.na(my.data.frame$V3),0,1)
我个人使用过,效果很好:
players_wd$APPROVED_WD[is.na(players_wd$APPROVED_WD)] <- 0
在 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