假设我有以下列表:
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
我想用0
替换所有NA
:
[[1]]
[1] 1 2 3 4 5 0 0
[[2]]
[1] 0
[[3]]
[1] 0 6 7 8 9 10
我最初认为is.na
会参与其中,但无法让它影响所有列表元素。我从相关问题(从列表列表中删除 NA(中了解到,使用 lapply
将允许我将is.na
应用于每个元素,但该帖子演示了如何删除(而不是替换(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
有多种方法可以做到这一点:
使用来自咕噜咕噜包的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
})
根据格雷戈尔的赞扬编辑
lapply(kk, function(i) {i[is.na(i)] <- 0; i})
我决定对提到的各种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
试试这个:
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