2013-03-23 29 views
11

Ciao caro, ho un problema con NaN. Sto lavorando con un set di dati di grandi dimensioni con molte variabili e hanno NaN. I dati sono in questo modo:Sostituire i valori NaN in un elenco con zero (0)

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

Ho usato questo i comandi per forzare la lista di frame di dati, ma ho ottenuto questo:

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' 

ho costretto z per frame di dati, ma non è stato sufficiente, forse c'è un modulo per cambiare NaN nell'elenco. Grazie per l'aiuto. Questo dato è solo un esempio: i miei dati originali hanno 36000 osservazioni e 40 variabili.

risposta

29

Questo è un caso di utilizzo perfetto per 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 avrebbe funzionato troppo, ma rapply offerte correttamente con liste annidate in questa situazione.

+1

+1 tu non spesso arriva a vedere 'rapply' in azione –

+0

@ricardosaporta avrei dovuto aggiungere "il caso d'uso raro" :-) –

+1

@ AriB.Friedman Questo non funziona per me, se cambiato in "is.null". Ho provato un <- elenco (1,2), lunghezza (a) <- 5, rapply (a, f = funzione (x) ifelse (is.null (x), 0, x), how = "replace ") e ottenuto valori NULL per 3-5. Sto provando a riempirlo con zero perché è troppo corto. –

3

Dopo la modifica dell'OP: Dopo il titolo modificato, questo dovrebbe farlo.

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 si dà automaticamente un data.frame se l'uscita risultante è di uguale lunghezza (a differenza del primo esempio, mostrato di seguito).


Vecchia soluzione (per continuità).

Prova questo:

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

# $b 
# [1] 2 3 5 8 

Nota 1: Sembra dal tuo post che si desidera sostituire NaN con 0. L'uscita del stack(z), può essere salvato a una variabile e poi sostituito a 0 e allora puoi unstack.

Nota 2: Inoltre, dal momento che na.omit rimuove NA e NaN, presumo anche che i tuoi dati non contengano NA (dai tuoi dati sopra).

7

Come non sembra importare avere i dati in un dataframe, è possibile fare anche qualcosa di altamente vettoriale. Tuttavia, questo funzionerà solo se ogni elemento dell'elenco è di uguale lunghezza. Sto indovinando i dati (36000/40 = 900) che questo è il caso:

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 
1
z = do.call(data.table, rapply(z, function(x) ifelse(is.nan(x),0,x), how="replace")) 

Se inizialmente hai data.table e si desidera 1-line la sostituzione.

Ma tenere a mente che sono necessità chiavi per essere ridefinito dopo che:

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