如何用R数据框中的零代替NA值?

我有一个data.frame和一些列有NA值。 我想用零replaceNA。 我如何做到这一点?

在@ 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包。 它有很多很好的function缺less数据分析。 =)

对于单个vector:

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

对于data.frame,从上面做一个函数,然后applyapply到列。

请在下面提供一个可重现的例子,详情如下:

如何做一个伟大的R可重现的例子?

dplyr例子:

 require(dplyr) df <- df %>% mutate(colname = ifelse(is.na(colname),0,colname)) 

dplyr的 mutate_all()将处理时间缩短了一半 – 简单的语法有助于保持大脑RAM可用于您的统计和科学工作。

mutate_all(funs(coalesce(., 0L)))

现在是最快最简洁的select;

尽pipe旧的替代混合动力车提供了几乎同样强大的select:
mutate_all(funs(replace(., is.na(.), 0))))

(如果你很难得到整数只能合并选项来压缩所有的列 – 你可能会select使用有条件地增强的mutate_if(is.integer, funs(coalesce(., 0L)))

 library(tidyverse) #The *microbenchmark* package provides an easy way to run a substantial number of trials library(microbenchmark) # Numerics replaced with numerics set.seed(24) dfN <- as.data.frame(matrix(sample(as.numeric(c(NA, 1:5)), 1e6 * 12, replace=TRUE), dimnames = list(NULL, paste0("var", 1:12)), ncol=12)) opN<- microbenchmark( baseR_replace = local(dfN %>% replace(., is.na(.), 0)), subsetReassign = local(dfN[is.na(dfN)] <- 0), mut_at_replace = local(dfN %>% mutate_at(funs(replace(., is.na(.), 0)), .vars = c(1:12))), mut_all_coalesce = local(dfN %>% mutate_all(funs(coalesce(., 0)))), mut_all_replace = local(dfN %>% mutate_all(funs(replace(., is.na(.), 0)))), replace_na = local(dfN %>% replace_na(list(var1 = 0, var2 = 0, var3 = 0, var4 = 0, var5 = 0, var6 = 0, var7 = 0, var8 = 0, var9 = 0, var10 = 0, var11 = 0, var12 = 0))), times = 1000L ) 

microbenchmark结果dataframe:

 print(opN) #standard data frame of the output 
 Unit: milliseconds expr min lq mean median uq max neval baseR_replace 354.7332 504.4715 535.5011 522.8615 548.0481 16272.1380 1000 subsetReassign 357.7277 503.4007 520.2998 518.7941 547.7761 1127.6515 1000 mut_at_replace 148.4641 162.9000 241.3715 183.3698 325.0781 449.3378 1000 mut_all_coalesce 149.9635 165.1787 240.9728 184.3331 327.1928 454.7660 1000 mut_all_replace 148.2156 162.7648 244.5988 187.7607 326.0433 530.8314 1000 replace_na 125.0847 139.1184 223.4409 167.6679 309.9594 443.4704 1000 

简单的boxplot结果:

 boxplot(opN) 

基准数字结果Boxplot

ggplot2 quickplot logplot:

 library(ggplot2) qplot(y=time, data=opN, colour=expr) + scale_y_log10() 

基准数字结果的DotTimePlot

特别感谢Tyler Rinker: https ://www.r-bloggers.com/microbenchmarking-with-r/和akrun: https ://stackoverflow.com/a/41530071/5088194和alexis_laz帮助我了解使用local()保持原始dataframe不变(并允许在一个级别的游戏场上比较子集操作)。

另外,正如alexis_laz在这里指出的那样,在可能的情况下,通过使用整数可以进一步缩短处理时间。 即:使用0L进行replace可以使用0replace速度。

 # Integers set.seed(24) dfL <- as.data.frame(matrix(sample(c(NA, 1L:5L), 1e6 * 12, replace=TRUE), dimnames = list(NULL, paste0("var", 1:12)), ncol=12)) opL <- microbenchmark( baseR_replace = local(dfL %>% replace(., is.na(.), 0L)), subsetReassign = local(dfL[is.na(dfL)] <- 0L), mut_at_replace = local(dfL %>% mutate_at(funs(replace(., is.na(.), 0L)), .vars = c(1:12))), mut_all_coalesce = local(dfL %>% mutate_all(funs(coalesce(., 0L)))), mut_all_replace = local(dfL %>% mutate_all(funs(replace(., is.na(.), 0L)))), replace_na = local(dfL %>% replace_na(list(var1 = 0L, var2 = 0L, var3 = 0L, var4 = 0L, var5 = 0L, var6 = 0L, var7 = 0L, var8 = 0L, var9 = 0L, var10 = 0L, var11 = 0L, var12 = 0L))), times = 1000L ) print(opL) #standard data frame of the output 
 Unit: milliseconds expr min lq mean median uq max neval baseR_replace 294.73478 333.48316 400.6349 351.6571 488.3390 1006.5461 1000 subsetReassign 298.68715 332.90326 401.3054 350.7967 494.5228 946.1093 1000 mut_at_replace 103.78118 119.71383 152.3932 127.8812 141.6276 357.3821 1000 mut_all_coalesce 106.09778 121.48774 150.6545 129.9593 142.5375 614.8059 1000 mut_all_replace 103.78247 119.77670 148.8508 127.9087 140.7524 358.6172 1000 replace_na 81.18997 96.82968 127.6435 104.1167 117.0925 384.2063 1000 

注意:尽pipeTidyrreplace_na在技​​术上是最快的,但它需要对所有variables名进行硬编码。 以相似的方式, mutate_at通常在mutate_at/all包的其余部分之前出现,但是对于replace值赋值则更加挑剔。

有关_at_all函数变体的好例子可以在这里find: https : _all

此外,我发现这是对dplyr(0.5.0)所带来的新function和改进function的精心总结: https ://blog.exploratory.io/dplyr-0-5-is-awesome-heres-why -be095fd4eb8a

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

定义这个函数:

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

现在,无论何时您需要将vector中的NA转换为零,您都可以执行:

 na.zero(some.vector) 

如果您在写入csv时尝试replaceNAs,则可以使用:

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

使用matrix或向量中的replace()NAreplace为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)) 

使用dplyr 0.5.0,你可以使用coalesce函数,通过coalesce(vec, 0)可以很容易地把它集成到%>%pipe道中。 这用0replace了vec所有NAs:

假设我们有一个NA s的数据框:

 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 

如果你想在因子variables中replaceNAs,这可能是有用的:

 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") 

它将因子vector转换为数字vector,并添加另一个人为数字因子等级,然后将其转换回因子vector,并带有一个额外的“NA等级”。

会评论@ ianmunoz的post,但我没有足够的声誉。 你可以结合dplyrmutate_eachreplace来照顾NA0replace。 使用@ 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_ ”的下划线。 我们也使用lazyeval / ~. 引用“我们正在使用的一切”,即数据框架。 现在有零了!

另一个例子使用imputeTS包:

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

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

tidyr方法replace_na另一个dplyrpipe道兼容选项,适用于多列:

 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) 

从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)