2011-09-06 18 views
17

Estoy tratando de eliminar NA s de mi marco de datos por interpolación con na.approx() pero no puedo eliminar todas las NA s.Interpolar valores de NA en un marco de datos con na.approx

Mi marco de datos es un 4096x4096 con 270.15 como indicador de valor no válido. Necesito que los datos sean continuos en todos los puntos para alimentar un modelo meteorológico. Ayer pregunté, y obtuve una respuesta, sobre cómo reemplazar valores en un marco de datos basado en otro marco de datos. Pero luego llegué al na.approx() y luego decidí reemplazar los valores 270.15 con NA y probar na.approx() para interpolar los datos. Pero la pregunta es por qué na.approx() no reemplaza todas las NA.

Esto es lo que estoy haciendo:

  • leer el archivo HDF original con hdf5load
  • subconjunto de la trama de datos (4094x4096)
  • valor del indicador Sustituir con NA

    > sst4[sst4 == 270.15 ] = NA 
    
  • Verificar la primera columna (o cualquier otra)

    > 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") 
    
  • Comprobar primera columna

    > 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 
    

Como se puede ver NA 411 de no se han eliminado. ¿Por qué? ¿Corresponden todos a los valores de columna principal/final?

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

¿Es necesario por na.approx tener valores válidos antes y después de NA para interpolar? ¿Debo configurar cualquier otra opción de na.approx?

Muchas gracias

Respuesta

12

Un pequeño ejemplo reproducibles:

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 

Sí, parece que usted no necesita los valores de inicio/final de columnas que se sabe o se la interpolación no funciona. ¿Puedes adivinar valores para tus límites?

OTRA EDICIÓN: Por lo tanto, de forma predeterminada, necesita que se conozcan los valores de inicio y fin de las columnas. Sin embargo, es posible obtener na.approx para completar siempre los espacios en blanco pasando rule = 2. Vea la respuesta de Félix. También puede usar na.fill para proporcionar un valor predeterminado, según el comentario de Gabor.Finalmente, puede interpolar las condiciones de contorno en dos direcciones (ver abajo) o adivinar las condiciones de contorno.


EDIT: Pensamiento adicional. Como na.approx solo se está interpolando en columnas, y sus datos son espaciales, quizás la interpolación en filas también sería útil. Entonces podrías tomar el promedio.

na.approx falla cuando las columnas enteras son NA, por lo que creamos un conjunto de datos más grande.

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

Ejecute na.approx en ambos sentidos.

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

Descubre la mejor conjetura.

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

Gracias Richie. Trataré de adivinar valores para los límites; como la extensión espacial de mi base de datos sst es mucho más grande que el dominio modelo que usaré, no estoy especialmente preocupado por los valores en los límites. Lo que realmente necesito es llenar los valores de NA en la región central del marco de datos. – pacomet

+0

Quien me rechazó, por favor puede dejar un comentario explicando lo que no le gustó. Si no proporciona comentarios, entonces no puedo mejorar la respuesta. –

+0

-1 No es cierto que necesite valores de inicio y fin. Los puntos finales se pueden extender como en la respuesta de Felix o en 'na.fill'. –

1

creo que debería tratar de establecer na.rm=TRUE

De los documentos

na.rm lógicas. ¿Deben eliminarse las NA principales?

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

+0

Hi Henrik. Si configuro na.rm = TRUE entonces obtengo un marco de datos de 3818x4096 y necesito conservar todos los valores de 4096x4096. – pacomet

+0

Hmm, ¿qué tal omitir la interpolación de fantasía y hacer un simple bucle que al ver una NA copia el último valor no NA? – Henrik

+0

Soy nuevo en R y tendré que buscar la sintaxis de bucle, estoy tratando de administrarlo con comandos básicos. ¿Cómo retengo el último valor no NA? ¿Qué sucede si el primer valor en la columna es NA? Además, prefiero una transición fluida entre los valores de datos. Estos son valores de la temperatura de la superficie del mar y las NA son puntos sobre la tierra donde el modelo cumplido necesita valores "realistas" para evitar problemas numéricos al resolver las ecuaciones. Gracias por tu sugerencia. – pacomet

9

na.approx() sigue la función approx() sólo en la interpolación de los valores, no extrapolación de ellos, de forma predeterminada. Sin embargo, como se describe en la página de ayuda para approx(), puede especificar rule = 2 para extrapolar como un valor constante del extremo más cercano. Siguiendo el ejemplo de Richie Algodón:

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 

De manera equivalente, puede utilizar "última observación llevar adelante" explícitamente.

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

Gracias por su respuesta. Funciona, pero tal vez no sea el mejor para mis datos. Como los datos son la temperatura de la superficie del mar, tal vez no sea una buena idea extrapolar como valor constante en caso de que los datos de NA estén sobre el mar (aunque la mayoría de los casos de NA son sobre puntos terrestres). – pacomet

+0

'na.approx (... rule = 2)' está gloriosamente indocumentado en la página de manual. Está enterrado en el documento PDF de 70 páginas. – smci

Cuestiones relacionadas