2011-09-06 11 views
17

Sto cercando di rimuovere NA s dal mio frame di dati per interpolazione con na.approx() ma non è possibile rimuovere tutti i NA s.Interpolare i valori NA in un frame di dati con na.approx

Il mio frame di dati è un 4096x4096 con 270.15 come flag per un valore non valido. Ho bisogno che i dati siano continui in tutti i punti per alimentare un modello meteorologico. Ieri ho chiesto e ottenuto una risposta su come sostituire i valori in un frame di dati basato su un altro frame di dati. Ma successivamente sono arrivato a na.approx() e ho deciso di sostituire i valori 270.15 con NA e provare na.approx() per interpolare i dati. Ma la domanda è perché na.approx() non sostituisce tutte le NA.

Questo è quello che sto facendo:

  • leggere il file HDF originale con hdf5load
  • sottoinsieme il frame di dati (4094x4096)
  • sostitutivo Valore contrassegna con NA

    > sst4[sst4 == 270.15 ] = NA 
    
  • Verifica la prima colonna (o qualsiasi altra)

    > summary(sst4[,1]) 
    
    Min. 1st Qu. Median Mean 3rd Qu. Max. NA's 
    271.3 276.4 285.9 285.5 292.3 302.8 1345.0 
    
  • Run na.approx

    > sst4=na.approx(sst4,na.rm="FALSE") 
    
  • Controllare prima colonna

    > summary(sst4[,1]) 
    Min. 1st Qu. Median Mean 3rd Qu. Max. NA's 
    271.3 276.5 286.3 285.9 292.6 302.8 411.0 
    

Come si può vedere 411 NA di non sono stati rimossi. Perché? Corrispondono tutti ai valori di colonna iniziale/finale?

head(sst4[,1]) 
[1] NA NA NA NA NA NA 
tail(sst4[,1]) 
[1] NA NA NA NA NA NA 

È necessario che na.approx abbia valori validi prima e dopo che NA venga interpolato? Devo impostare qualsiasi altra opzione na.approx?

La ringrazio molto

risposta

12

Un piccolo, ad esempio riproducibile:

library(zoo) 
set.seed(1) 
m <- matrix(runif(16, 0, 100), nrow = 4) 
missing_values <- sample(16, 7) 
m[missing_values] <- NA 
m 
     [,1]  [,2]  [,3]  [,4] 
[1,] 26.55087 20.16819 62.911404 68.70228 
[2,] 37.21239  NA 6.178627 38.41037 
[3,]  NA  NA  NA  NA 
[4,] 90.82078 66.07978  NA  NA 

na.approx(m) 
     [,1]  [,2]  [,3]  [,4] 
[1,] 26.55087 20.16819 62.911404 68.70228 
[2,] 37.21239 35.47206 6.178627 38.41037 
[3,] 64.01658 50.77592  NA  NA 
[4,] 90.82078 66.07978  NA  NA 

m[4, 4] <- 50 
na.approx(m) 
     [,1]  [,2]  [,3]  [,4] 
[1,] 26.55087 20.16819 62.911404 68.70228 
[2,] 37.21239 35.47206 6.178627 38.41037 
[3,] 64.01658 50.77592  NA 44.20519 
[4,] 90.82078 66.07978  NA 50.00000 

Yup, sembra che si ha bisogno dei valori di inizio/fine di colonne da noti o l'interpolazione non funziona. Riesci a indovinare valori per i tuoi confini?

UN ALTRO MODIFICO: Quindi, per impostazione predefinita, è necessario conoscere i valori iniziali e finali delle colonne. Tuttavia è possibile ottenere na.approx per riempire sempre gli spazi vuoti passando rule = 2. Vedi la risposta di Felix. È inoltre possibile utilizzare na.fill per fornire un valore predefinito, come da commento di Gabor.Infine, puoi interpolare le condizioni al contorno in due direzioni (vedi sotto) o intuire le condizioni al contorno.


EDIT: Un ulteriore pensiero. Poiché na.approx è solo interpolato in colonne e i dati sono spaziali, sarebbe utile anche l'interpolazione nelle righe. Quindi potresti prendere la media.

na.approx non riesce quando intere colonne sono NA, quindi creiamo un set di dati più grande.

set.seed(1) 
m <- matrix(runif(64, 0, 100), nrow = 8) 
missing_values <- sample(64, 15) 
m[missing_values] <- NA 

Corsa na.approx in entrambe le direzioni.

by_col <- na.approx(m) 
by_row <- t(na.approx(t(m))) 

Trova l'ipotesi migliore.

default <- 50 
best_guess <- ifelse(is.na(by_row), 
    ifelse(
    is.na(by_col), 
    default,    #neither known 
    by_col    #only by_col known 
), 
    ifelse(
    is.na(by_col), 
    by_row,    #only by_row known 
    (by_row + by_col)/2 #both known 
) 
) 
+0

Grazie Richie. Proverò a indovinare i valori per i limiti; poiché l'estensione spaziale del mio database sst è molto più grande del dominio del modello met che userò, non sono particolarmente preoccupato per i valori ai limiti. Quello di cui ho realmente bisogno è di riempire i valori di NA nella regione centrale del frame di dati. – pacomet

+0

Chi mi ha messo in votazione, per favore puoi lasciare un commento che spieghi cosa non ti è piaciuto. Se non fornisci feedback, non posso migliorare la risposta. –

+0

-1 non è vero che hai bisogno di valori iniziali e finali. I punti finali possono essere estesi come nella risposta di Felix o in "na.fill". –

1

Penso che si dovrebbe cercare di impostare na.rm=TRUE

Dalla documentazione

na.rm logiche. Dovrebbero essere rimosse le NAs?

http://www.oga-lab.net/RGM2/func.php?rd_id=zoo:na.approx

+0

Ciao Henrik. Se imposto na.rm = TRUE, ricevo un frame di dati 3818x4096 e devo conservare tutti i valori 4096x4096. – pacomet

+0

Hmm, che ne dici di saltare l'interpolazione di fantasia e fare un semplice ciclo che quando si vede un NA copia l'ultimo valore non NA? – Henrik

+0

Sono nuovo a R e dovrò cercare la sintassi del loop, sto cercando di gestire con i comandi di base. Come posso mantenere l'ultimo valore non NA? Cosa succede se il primo valore nella colonna è NA? Inoltre, preferisco una transizione graduale tra i valori dei dati. Questi sono valori di temperatura superficiale del mare e NA sono punti su terreni in cui il modello met ha bisogno di valori "realistici" per evitare problemi numerici durante la risoluzione delle equazioni. Grazie per il tuo suggerimento – pacomet

9

na.approx() segue la funzione approx() solo interpolando valori, non li estrapolando, per default. Tuttavia, come descritto nella pagina della guida per approx(), è possibile specificare rule = 2 per estrapolare come valore costante dell'estremo più vicino. Seguendo l'esempio di Richie Cotton:

na.approx(m, rule = 2) 
     [,1]  [,2]  [,3]  [,4] 
[1,] 26.55087 20.16819 62.911404 68.70228 
[2,] 37.21239 35.47206 6.178627 38.41037 
[3,] 64.01658 50.77592 6.178627 38.41037 
[4,] 90.82078 66.07978 6.178627 38.41037 

Equivalentemente, è possibile utilizzare "ultima osservazione riporto" in modo esplicito.

na.locf(na.approx(m)) 
## "first observation carry backwards" too: 
na.locf(na.locf(na.approx(m)), fromLast = TRUE) 
+0

Grazie per la risposta. Funziona ma forse non è il buono per i miei dati. Poiché i dati sono la temperatura superficiale del mare, forse non è una buona idea estrapolare come valore costante nel caso in cui i dati di NA siano sopra il mare (sebbene la maggior parte dei casi di NA si trovino su punti terrestri) dove la transizione regolare tra i punti della griglia è ciò che di solito si trova. – pacomet

+0

'na.approx (... rule = 2)' è gloriosamente non documentato nella manpage! È sepolto nel documento PDF di 70 pagine. – smci

Problemi correlati