如何将20个列中的NA替换为0?

18

我希望在20个列中将NA替换为0。我发现了这种方法适用于2列,但我认为如果列数为20,则不是最佳选择。是否有其他更紧凑的解决方案?

mydata[,c("a", "c")] <-
        apply(mydata[,c("a","c")], 2, function(x){replace(x, is.na(x), 0)})

更新: 为了简单起见,我们采用这个包含8列的数据,并将b、c、e、f和d列中的NA替换掉。
a  b  c  d  e  f  g  d
1  NA NA 2  3  4  7  6
2  g  3  NA 4  5  4  Y
3  r  4  4  NA t  5  5

结果必须是这个:
a  b  c  d  e  f  g  d
1  0  0  2  3  4  7  6
2  g  3  NA 4  5  4  Y
3  r  4  4  0  t  5  5

发布一些数据进行测试。 - Avinash Raj
1
只需执行 cols <- c("b", "c", "e", "f"); mydf[cols] <- replace(mydf[cols], is.na(mydf[cols]), 0) - A5C1D2H2I1M1N2O1R2T1
你真的有两个名为 d 的列吗? - Rich Scriven
如果列是连续的,请使用start:end而不是c()。 - R. Schifini
6个回答

18

tidyr 中的 replace_na 函数不仅可以应用于数据框,也可以应用于向量 (http://tidyr.tidyverse.org/reference/replace_na.html)。

结合 dplyr 中的 mutate_at 变体,可同时将其应用于多个列:

my_data %>% mutate_at(vars(b,c,e,f), replace_na, 0)
或者
my_data %>% mutate_at(c('b','c','e','f'), replace_na, 0)

不知道为什么,但只有 vars() 版本对我起作用。 - stevec
谢谢您!我一直在尝试想出一种简洁的方法来做这件事,但没有想到可以使用vars()。 - Andrew Brēza

8

这是一种使用tidyverse的方法,根据列的数据类型用不同的值替换NA。

library(tidyverse)

dataset %>% mutate_if(is.numeric, replace_na, 0) %>%  
    mutate_if(is.character, replace_na, "")

6

使用 tidyr::replace_na() 的另一种策略

library(tidyverse)

df <- read.table(header = T, text = 'a  b  c  d  e  f  g  h
1  NA NA 2  3  4  7  6
2  g  3  NA 4  5  4  Y
3  r  4  4  NA t  5  5')

df %>%
  mutate(across(everything(), ~replace_na(., 0)))
#>   a b c d e f g h
#> 1 1 0 0 2 3 4 7 6
#> 2 2 g 3 0 4 5 4 Y
#> 3 3 r 4 4 0 t 5 5

本文创建于2021-08-22,使用reprex 软件包 (v2.0.0)。


你没有展示如何替换指定列中的 NA,而这正是实际所要求的。 - jay.sf

5

另一种选择:

library(tidyr)
v <- c('b', 'c', 'e', 'f')
replace_na(df, as.list(setNames(rep(0, length(v)), v)))

这将会产生:

#  a b c  d e f g d.1
#1 1 0 0  2 3 4 7   6
#2 2 g 3 NA 4 5 4   Y
#3 3 r 4  4 0 t 5   5

4

我们可以使用 qdap 中的 NAer 将 NA 转换为 0。如果有多列,可以使用 lapply 循环。

library(qdap)
nm1 <- c('b', 'c', 'e', 'f')
mydata[nm1] <- lapply(mydata[nm1], NAer)
mydata
#  a b c  d e f g d.1
#1 1 0 0  2 3 4 7   6
#2 2 g 3 NA 4 5 4   Y
#3 3 r 4  4 0 t 5   5

或者使用dplyr

library(dplyr)
mydata %>% 
   mutate_each_(funs(replace(., which(is.na(.)), 0)), nm1)
#  a b c  d e f g d.1
#1 1 0 0  2 3 4 7   6
#2 2 g 3 NA 4 5 4   Y
#3 3 r 4  4 0 t 5   5

但是我在哪里定义列名,在这些列中,NA应该被0替换?我不需要在所有列中将NA替换为0。 - Klausos Klausos

3

了解到replace_na()函数可以接受一个命名列表作为replace参数,使用purrr::map()是减少代码量的好方法。同时也可以使用map2()来在每个列中替换不同的值。

代码:

library(data.table)
library(tidyverse)

tbl <-read_table("a  b  c  d  e  f  g  d
1  NA NA 2  3  4  7  6
2  g  3  NA 4  5  4  Y
3  r  4  4  NA t  5  5")
#> Warning: Duplicated column names deduplicated: 'd' => 'd_1' [8]
nms <- c('b', 'c', 'e', 'f', 'g')

imap_dfc(tbl, ~ if(any(.y == nms)) replace_na(.x, 0) else .x) 
#> # A tibble: 3 × 8
#>       a b         c     d     e f         g d_1  
#>   <dbl> <chr> <dbl> <dbl> <dbl> <chr> <dbl> <chr>
#> 1     1 0         0     2     3 4         7 6    
#> 2     2 g         3    NA     4 5         4 Y    
#> 3     3 r         4     4     0 t         5 5
#using data.table

tblDT <- as.data.table(tbl)

#Further explanation here: https://dev59.com/z2Qn5IYBdhLWcg3wa2mV
tblDT[, (nms) := map(.SD, ~replace_na(., 0)), .SDcols = nms]

tblDT %>% 
  as_tibble()
#> # A tibble: 3 × 8
#>       a b         c     d     e f         g d_1  
#>   <dbl> <chr> <dbl> <dbl> <dbl> <chr> <dbl> <chr>
#> 1     1 0         0     2     3 4         7 6    
#> 2     2 g         3    NA     4 5         4 Y    
#> 3     3 r         4     4     0 t         5 5
#to replace na's in every column:

tbl %>%
  replace_na(map(., ~0))
#> # A tibble: 3 × 8
#>       a b         c     d     e f         g d_1  
#>   <dbl> <chr> <dbl> <dbl> <dbl> <chr> <dbl> <chr>
#> 1     1 0         0     2     3 4         7 6    
#> 2     2 g         3     0     4 5         4 Y    
#> 3     3 r         4     4     0 t         5 5

此内容由reprex 包 (v2.0.1) 于2021-09-25创建。


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