web-dev-qa-db-fra.com

Remplacer les valeurs NaN dans une liste par zéro (0)

Bonjour mon cher, j'ai un problème avec NaN. Je travaille avec un grand ensemble de données avec beaucoup de variables et elles ont NaN. Les données sont comme ceci:

z=list(a=c(1,2,3,NaN,5,8,0,NaN),b=c(NaN,2,3,NaN,5,8,NaN,NaN))

J'ai utilisé ces commandes pour forcer la liste à la trame de données mais j'ai eu ceci:

z=as.data.frame(z)
> is.list(z)
[1] TRUE

> is.data.frame(z)
[1] TRUE
> replace(z,is.nan(z),0) 
Error en is.nan(z) : default method not implemented for type 'list'

J'ai forcé z à trame de données, mais cela ne suffisait pas. Il existe peut-être un formulaire pour modifier NaN dans la liste. Merci de votre aide. Ces données ne sont qu'un exemple. Mes données d'origine comportent 36 000 observations et 40 variables.

13
Duck

C'est un cas d'utilisation parfait pour 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 fonctionnerait aussi, mais rapply traite correctement les listes imbriquées dans cette situation.

31
Ari B. Friedman

Comme vous ne semblez pas vous préoccuper d'avoir vos données dans une base de données, vous pouvez aussi faire quelque chose de très vectorisé. Toutefois, cela ne fonctionnera que si chaque élément de la liste est de longueur égale. Je devine dans vos données (36000/40 = 900) que c'est le cas:

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
7
Simon O'Hanlon

Après l'édition de OP: Après votre titre édité, cela devrait le faire.

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 vous donne automatiquement un data.frame si la sortie résultante est de longueur égale (contrairement au premier exemple présenté ci-dessous).


Ancienne solution (pour la continuité).

Essaye ça:

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

# $b
# [1] 2 3 5 8

Note 1: Il semble dans votre message que vous souhaitez remplacer NaN par 0. La sortie de stack(z) peut être enregistrée dans une variable, puis remplacée par 0 et vous pouvez donc unstack.

Note 2: De plus, puisque na.omit supprime NA ainsi que NaN, je suppose également que vos données ne contiennent pas de NA (à partir de vos données ci-dessus). 

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

Si vous avez initialement data.table et que vous souhaitez remplacer le 1 ligne.

Mais gardez à l’esprit que les clés doivent être redéfinies après cela:

> key(x1)
[1] "date"
> x1 = do.call(data.table, rapply(x1, function(x) ifelse(is.na(x), 0, x), how="replace"))
> key(x1)
NULL
1
dmitry