Replace NaN values in a list with zero (0)

白昼怎懂夜的黑 提交于 2019-11-28 09:10:50

This is a perfect use case for rapply.

> rapply( z, f=function(x) ifelse(is.nan(x),0,x), how="replace" )
$a
[1] 1 2 3 0 5 8 0 0

$b
[1] 0 2 3 0 5 8 0 0

lapply would work too, but rapply deals properly with nested lists in this situation.

As you don't seem to mind having your data in a dataframe, you can do something highly vectorised too. However, this will only work if each list element is of equal length. I am guessing in your data (36000/40 = 900) that this is the case:

z <- as.data.frame(z)
dim <- dim(z)
y <- unlist(z)
y[ is.nan(y) ] <- 0
x <- matrix( y , dim )
#        [,1] [,2]
#   [1,]    1    0
#   [2,]    2    2
#   [3,]    3    3
#   [4,]    0    0
#   [5,]    5    5
#   [6,]    8    8
#   [7,]    0    0
#   [8,]    0    0

Following OP's edit: Following your edited title, this should do it.

unstack(within(stack(z), values[is.nan(values)] <- 0))
#   a b
# 1 1 0
# 2 2 2
# 3 3 3
# 4 0 0
# 5 5 5
# 6 8 8
# 7 0 0
# 8 0 0

unstack automatically gives you a data.frame if the resulting output is of equal length (unlike the first example, shown below).


Old solution (for continuity).

Try this:

unstack(na.omit(stack(z)))
# $a
# [1] 1 2 3 5 8 0

# $b
# [1] 2 3 5 8

Note 1: It seems from your post that you want to replace NaN with 0. The output of stack(z), it can be saved to a variable and then replaced to 0 and then you can unstack.

Note 2: Also, since na.omit removes NA as well as NaN, I also assume that your data contains no NA (from your data above).

z = do.call(data.table, rapply(z, function(x) ifelse(is.nan(x),0,x), how="replace"))

If you initially have data.table and want to 1-line the replacement.

But keep in mind that keys are need to be redefined after that:

> key(x1)
[1] "date"
> x1 = do.call(data.table, rapply(x1, function(x) ifelse(is.na(x), 0, x), how="replace"))
> key(x1)
NULL
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!