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

How do I replace NA values with zeros in an R dataframe?

提问人:Renato Dinhani 提问时间:11/17/2011 最后编辑:MaëlRenato Dinhani 更新时间:5/8/2023 访问量:2050855

问:

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

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

数据帧 R-常见问题解答

评论

16赞 Ben Bolker 11/17/2011
stackoverflow.com/questions/7279089/ 的小修改... (我通过搜索“[r] 将 NA 替换为零”找到)......
0赞 8/17/2022
@psychonomics您的评论和热门答案有什么区别?
1赞 psychonomics 8/25/2022
@svp - 也许什么都没有?我看不到我的评论。有没有可能我删除了它,你仍然可以查看?

答:

160赞 Ari B. Friedman 11/17/2011 #1

对于单个向量:

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

对于 data.frame,从上面创建一个函数,然后将其转换为列。apply

下次请提供一个可重现的例子,详见这里:

如何制作一个伟大的 R 可重现示例?

评论

20赞 aL3xa 11/17/2011
is.na是泛型函数,并且具有类对象的方法。 所以这个也适用于 S!data.framedata.frame
3赞 aL3xa 11/18/2011
当我第一次跑步时,我就像哇?!?一样。我喜欢这样的事情发生!=)methods(is.na)
10赞 Mark Miller 2/22/2013
假设您有一个名为 df 的数据框而不是单个向量,并且您只想替换名为 X3 的单个列中缺失的观测值。您可以使用以下行执行此操作:df$X3[is.na(df$X3)] <- 0
9赞 Mark Miller 3/20/2013
假设您只想在名为 my.df 的数据框的第 4-6 列中将 NA 替换为 0。您可以使用:my.df[,4:6][is.na(my.df[,4:6])] <- 0
0赞 uh_big_mike_boi 4/8/2016
你怎么会把'x'传递给 is.na(x)有没有办法判断R中的哪些库例程是矢量化的?
1153赞 aL3xa 11/17/2011 #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

评论

3赞 Renato Dinhani 11/17/2011
在你发布之前,我昨天已经尝试过这个代码,但没有用。因为这个我发布了问题。但我试着知道并完美地工作。我想我做错了什么。
15赞 Aaron left Stack Overflow 11/18/2011
@RenatoDinhaniConceição:如果您已经尝试过某些东西,那么在提出问题时分享这些信息会很有帮助;它有助于缩小问题可能出在哪里。
2赞 user798719 4/4/2015
d[is.na(d)] <-0 对我来说没有意义。似乎是倒退了?R 如何处理此语句?
18赞 Twitch_City 7/30/2015
@user798719 - “<-” 是 R 的赋值运算符,可以理解为:在右侧做某事,然后将其赋值给左侧的位置/名称。在这种情况下,我们并没有真正“做”任何事情——只是做零。左边是说:看d对象,在d对象里面(方括号),找到所有返回TRUE的元素(is.na(d)为每个元素返回一个逻辑)。找到它们后,将它们(“分配它们”)替换为值 0。这些保留所有非 NA 原样,并且只替换缺失的 NA。
7赞 jtdoud 2/10/2017
和。。。如果您有一个数据框,并且只想将替换应用于特定的 nurmeric 向量(留下 say...带有 NA 的字符串):df[19:28][is.na(df[19:28])] <- 0
6赞 Zahra 3/30/2013 #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

评论

6赞 dardisco 4/8/2013
没错,但只有当你知道向量中 s 的索引时才实用。它适用于小向量,如您的示例所示。NA
5赞 lmo 1/18/2017
@dardisco将在不显式列出索引值的情况下工作。x1 <- replace(x,is.na(x),1)
69赞 mrsoltys 2/22/2014 #4

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

  write.csv(data, "data.csv", na = "0")
95赞 ianmunoz 5/9/2014 #5

dplyr 示例:

library(dplyr)

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

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

58赞 krishan404 9/24/2015 #6

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

定义此函数:

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

现在,每当您需要将向量中的 NA 转换为零时,您都可以执行以下操作:

na.zero(some.vector)

评论

0赞 Friede 12/6/2023
return(x)不需要,就足够了。x
32赞 Charleslmh 2/25/2016 #7

更通用的方法,即使用 in 矩阵或向量替换replace()NA0

例如:

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

这也是在ifelse()dplyr

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

评论

3赞 Climbs_lika_Spyder 6/23/2016
我的色谱柱是一个因素,所以我必须添加我的替换值levels(A$x) <- append(levels(A$x), "notAnswered") A$x <- replace(A$x,which(is.na(A$x)),"notAnswered")
1赞 lmo 1/18/2017
which这里不需要,你可以使用 .x1 <- replace(x,is.na(x),1)
0赞 Gerry 5/17/2017
我尝试了此线程中提出的许多方法,以替换大型数据框中的一个特定列,并且此函数最有效,但也最简单。NA0replace()
11赞 user6075957 3/17/2016 #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 水平”。

13赞 reidjax 5/20/2016 #9

本来会评论@ianmunoz的帖子,但我没有足够的声誉。您可以组合 ' 和 来处理替换。使用 @aL3xa 答案中的数据帧...dplyrmutate_eachreplaceNA0

> 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),这就是为什么我们需要在“.”我们还使用 's / 和引用“我们正在处理的一切”,即数据帧。现在有零!funs_lazyevalinterp~.

31赞 Psidom 9/17/2016 #10

在 0.5.0 中,您可以使用可以轻松集成到流水线中的功能。这会将 0 中的所有 NA 替换为:dplyrcoalesce%>%coalesce(vec, 0)vec

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

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

评论

0赞 Arthur Yip 7/4/2017
我测试了合并,它的性能与替换大致相同。coalesce 命令是迄今为止最简单的命令!
3赞 jangorecki 5/30/2019
如果您能介绍如何在 2+ 列的所有列上应用它,那将很有用 Tibble.
0赞 LMc 6/7/2023
mutate(across(where(is.character), ~ coalesce(.x, 0)))
4赞 Antti 10/10/2016 #11

另一个管道兼容选项,其方法适用于多个列:dplyrtidyrreplace_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赞 Steffen Moritz 11/11/2016 #12

另一个使用 imputeTS 包的例子:

library(imputeTS)
na.replace(yourDataframe, 0)
470赞 leerssej 1/11/2017 #13

dplyr 混合选项现在比 Base R 子集重新分配快 30% 左右。在 100M 数据点上,数据帧的运行速度比基本 R 选项快半秒。人们特别要避免的是使用 或 .(完整的 600 项试验分析持续了 4.5 小时以上,主要是因为包括了这些方法。有关完整结果,请参阅下面的基准分析。mutate_all(~replace(., is.na(.), 0))d[is.na(d)] <- 0ifelse()if_else()

如果您正在为海量数据帧而苦苦挣扎,这是最快的选择:比标准 Base R 方法快 40%。它还可以就地修改数据,有效地允许您一次处理近两倍的数据。data.table


其他有用的 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))
  • 或者代替 , try ,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))

##The 完整分析 - 针对 dplyr 0.8.0 进行了更新:函数使用 purrr 格式 ~ symbols:替换已弃用的 funs() 参数。

###Approaches 测试:

# 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)}

###The 此分析的代码:

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(
    hybrd.ifelse     = hybrd.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
)

###Summary 结果

> 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

##结果 #Boxplot

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

Boxplot Comparison of Elapsed Time

颜色编码的试验散点图(对数刻度上带有 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)))

Scatterplot of All Trial Times

关于其他高绩效人员的说明

当数据集变大时,Tidyr's 历来会走在前面。由于当前收集了 100M 个数据点,因此它的性能几乎与 Base R For 循环完全相同。我很好奇不同大小的数据帧会发生什么。replace_na

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

归属和赞赏

特别鸣谢:

  • Tyler RinkerAkrun 演示了微基准测试。
  • alexis_laz努力帮助我理解 的用法,以及(在弗兰克的耐心帮助下)无声胁迫在加速许多这些方法方面所起的作用。local()
  • ArthurYip for the poke 添加较新的函数并更新分析。coalesce()
  • Gregor 推动弄清楚这些功能,最终将它们包含在阵容中。data.table
  • 基础 RFor 循环:alexis_laz
  • data.table For 循环:Matt_Dowle
  • Roman 解释了真正测试的内容。is.numeric()

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

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

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

评论

2赞 leerssej 3/8/2017
@Frank - 感谢您发现这种差异。引用全部被清理,结果已在一台机器上完全重新运行并重新发布。
0赞 Frank 3/8/2017
好的,谢谢。另外,我认为是错误的,应该是df1[j][is.na(df1[j])] = 0df1[[j]][is.na(df1[[j]])] = 0
1赞 leerssej 4/24/2017
@UweBlock - 很好的问题:它允许我执行子集左分配操作,所有函数都在完全相同的数据帧上工作。既然我不得不围绕这个功能来包装本地,那么以科学的名义[一份工作,你有一份工作!我把它包裹在所有这些人身上,这样竞争环境就明确地公平了。欲了解更多信息 - 请看这里:stackoverflow.com/questions/41604711/...我已经删减了之前相当冗长的答案 - 但讨论的那部分会很好补充。谢谢!
1赞 leerssej 7/11/2017
@ArthurYip - 我已经添加了该选项并一直重新运行。感谢您的更新推动。coalesce()
5赞 Jeff Parker 8/18/2020
dplyr 1.0.2 的更新删除了 和 :mutate_atmutate_allfunction(x) { mutate(across(x, ~replace_na(., 0))) }
3赞 Fábio 4/12/2017 #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)
69赞 Sasha 1/14/2019 #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))) 

评论

2赞 Ömer An 4/13/2021
mutate_*动词现在被across()
0赞 Faustin Gashakamba 8/29/2022
我很好奇为什么我需要将函数包装在里面。为什么不直接将其送入管道呢?replace(is.na(.), 0)mutate()
0赞 Julien 10/27/2022
mutate允许创建或替换变量。
0赞 ha-pu 3/24/2023
这就是您应该如何编写替换dplyr 1.1.0mutate(data, across(.cols = everything(), \(x) replace_na(x, 0)))
0赞 LMc 6/7/2023
@ha-pu 从 1.1.0 开始,匿名函数现在支持内联(不一定取代),并且确实提供了轻微的性能提升。~
11赞 jangorecki 2/3/2019 #16

专用函数,并且 ,用于此目的。 只要可用,它们就会分发要在多个线程上计算的列。nafillsetnafilldata.table

library(data.table)

ans_df <- nafill(df, fill=0)

# or even faster, in-place
setnafill(df, fill=0)
3赞 davsjob 6/11/2019 #17

一种简单的编写方法是:if_nahablar

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
0赞 Seyma Kalay 10/31/2019 #18

如果要在更改特定列中的NA后分配新名称,在本例中为V3列,请使用“也可以这样做”

my.data.frame$the.new.column.name <- ifelse(is.na(my.data.frame$V3),0,1)
26赞 Oliver Oliver 5/11/2020 #19

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

df %>% replace(is.na(.), 0)

评论

3赞 jogo 5/11/2020
这不是一个新的解决方案
6赞 MS Berends 7/9/2020 #20

该包有一个泛型,默认情况下用零替换数值,用今天替换逻辑,以此类推:cleanerna_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

0赞 polkas 9/24/2020 #21

我想添加下一个使用流行的 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* 

可以看出,所有插补元数据都作为属性进行分配。因此,它可以在以后使用。

-1赞 wesleysc352 12/30/2020 #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   
7赞 LMc 4/1/2021 #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

此代码将强制为第一列中的字符。要根据列类型进行替换,您可以在以下公式中使用类似咕噜声的公式:0NAwhere

df %>% 
  mutate(across(where(~ anyNA(.) & is.character(.)), ~ replace_na(., "0")))
0赞 John Haberstroh 7/29/2021 #24

这并不是一个新的解决方案,但我喜欢编写内联 lambda 来处理我无法让包做的事情。在本例中,

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

因为 R 永远不会像您在 Python 中看到的那样“按对象传递”,所以此解决方案不会修改原始变量,因此将执行与大多数其他解决方案完全相同的功能,但对特定包的复杂知识的需求要少得多。df

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

8赞 Gautam Mokal 8/31/2021 #25

无需使用任何库。

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

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

df
2赞 Rupesh Kumar 11/3/2021 #26

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

  1. 带有列的数据框

A$name[is.na(A$name)]<-0

A$name[is.na(A$name)]<-“NA”

  1. 包含所有数据帧

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

  1. 将数据框中的 NA 替换为空白

df[is.na(df)]<-“”

  1. 将 NULL 替换为 NA

df[is.null(df)] <- 不适用

-1赞 Aymen Azoui 9/9/2022 #27

我个人使用过它并且工作正常:

players_wd$APPROVED_WD[is.na(players_wd$APPROVED_WD)] <- 0

评论

2赞 Tyler2P 3/30/2023
通过添加有关代码的作用以及它如何帮助 OP 的更多信息,可以改进您的答案。
0赞 jaeyeon 12/10/2022 #28

这是一个更灵活的解决方案。无论您的数据框有多大,或者 或 或 任何东西表示零,它都可以工作。0zero

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`
0赞 Quinten 1/16/2023 #29

另一个选项是用零替换 all。以下是一些可重现的代码(来自@aL3xa的数据):sapplyNA

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-01-15 with reprex v2.0.2


请注意:从 R 4.1.0 开始,您可以使用 .\(x)function(x)

1赞 Maël 5/8/2023 #30

另一种选择是使用 .默认情况下,将 NA 替换为 0。collapse::replace_NAreplace_NA

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