替换 R 中多个列表元素中的 NA

Replace NAs in multiple list elements in R

假设我有以下列表:

list(c(1:5,NA,NA),NA,c(NA,6:10))

[[1]]
[1]  1  2  3  4  5 NA NA

[[2]]
[1] NA

[[3]]
[1] NA  6  7  8  9 10

我想将所有 NA 替换为 0:

[[1]]
[1] 1 2 3 4 5 0 0

[[2]]
[1] 0

[[3]]
[1]  0  6  7  8  9 10

我原本以为 is.na 会涉及,但无法影响所有列表元素。我从相关问题 (Remove NA from list of lists) 中了解到,使用 lapply 将允许我将 is.na 应用于每个元素,但是 post 演示了如何删除(不是 替换) NA 值。

如何替换 NA 来自多个 列表元素的值?

我已经尝试了 for 循环和 ifelse 方法,但我尝试过的所有方法要么很慢,要么不起作用,要么就是笨拙。必须有一个简单的方法来使用 apply 函数...

还有

这是使用 replace 函数的简单 lapply 方法:

L1 <-list(c(1:5,NA,NA),NA,c(NA,6:10))

lapply(L1, function(x) replace(x,is.na(x),0))

想要的结果:

[[1]]
[1] 1 2 3 4 5 0 0

[[2]]
[1] 0

[[3]]
[1]  0  6  7  8  9 10

有多种方法可以做到这一点:

使用来自 purrrr 包的 map

lt <- list(c(1:5,NA,NA),NA,c(NA,6:10))
lt %>% 
    map(~replace(., is.na(.), 0))


#output

[[1]]
[1] 1 2 3 4 5 0 0

[[2]]
[1] 0

[[3]]
[1]  0  6  7  8  9 10
kk<- list(c(1:5,NA,NA),NA,c(1,6:10))

lapply(kk, function(i) 
  { p<- which(is.na(i)==TRUE)
    i[p] <- 0
    i
  })

根据 Gregor 的评论进行编辑

lapply(kk, function(i) {i[is.na(i)] <- 0; i})

试试这个:

lapply(enlist, function(x) { x[!is.na(x)]})

其中:

enlist <- list(c(1:5,NA,NA),NA,c(NA,6:10))

这产生:

[[1]]
[1] 1 2 3 4 5

[[2]]
logical(0)

[[3]]
[1]  6  7  8  9 10

我决定对提到的各种lapply方法进行基准测试:

lapply(Lt, function(x) replace(x,is.na(x),0)) 
lapply(Lt, function(x) {x[is.na(x)] <- 0; x})
lapply(Lt, function(x) ifelse(is.na(x), 0, x)) 

基准代码:

Lt <- lapply(1:10000, function(x)  sample(c(1:10000,rep(NA,1000))) )    ##Sample list

elapsed.time <- data.frame(
    m1 = mean(replicate(25,system.time(lapply(Lt, function(x) replace(x,is.na(x),0)))[3])),
    m2 = mean(replicate(25,system.time(lapply(Lt, function(x) {x[is.na(x)] <- 0; x}))[3])),
    m3 = mean(replicate(25,system.time(lapply(Lt, function(x) ifelse(is.na(x), 0, x)))[3]))
  )

结果:

Function                                          Average Elapsed Time
lapply(Lt, function(x) replace(x,is.na(x),0))     0.8684 
lapply(Lt, function(x) {x[is.na(x)] <- 0; x})     0.8936
lapply(Lt, function(x) ifelse(is.na(x), 0, x))    8.3176

replace 方法最快,紧随其后的是 [] 方法。 ifelse 方法慢 10 倍。

这将处理任何列表深度和结构:

x <-  eval(parse(text=gsub("NA","0",capture.output(dput(a)))))
# [[1]]
# [1] 1 2 3 4 5 0 0
# 
# [[2]]
# [1] 0
# 
# [[3]]
# [1]  0  6  7  8  9 10