2012-02-24 24 views
40

Tengo una matriz (2601 por 58) de las estimaciones de concentración de materia particulada de un modelo de calidad del aire. Debido a que los monitores de calidad del aire de la vida real no pueden medir por debajo de 0.1 ug/L, necesito reemplazar todos los valores en mi matriz que son <0.1 con un valor cero/NA/nulo.Reemplazar todos los valores en una matriz <0.1 con 0

Alguien sugirió ifelse(test, true, false) con una declaración lógica, pero cuando intento esto, elimina todo.

+2

La pregunta sobre con qué reemplazar los valores negativos o cero es interesante. Debido a que muchos modelos se construyen sobre una base de registro (y), a menudo los reemplazo con el punto medio entre el límite inferior de normal y cero. (Probablemente una pregunta secundaria mejor planteada en stats.exchange.) –

+0

@Dwin, +1 a ese comentario. Me gustaría ver esa segunda pregunta, y sus respuestas en crossvalidated.com –

+0

es un comentario interesante. Veo lo que está diciendo ... Para el contexto, estoy usando estos valores en una regresión con datos del departamento de emergencias (estudio de epidemiología de la población). La explicación que me dieron de por qué reemplazar el <0.1 con 0 fue que no queremos sobreestimar el efecto ... ¿algo que ver con "cero inflado"? – mEvans

Respuesta

39

ifelse debería funcionar:

mat <- matrix(runif(100),ncol=5) 
mat <- ifelse(mat<0.1,NA,mat) 

Pero yo elegiría la respuesta de Harlan sobre la mía.

mat[mat < 0.1] <- NA 
+0

Lo que pasa con ifelse es que parece convertir mi matriz en un vector ... ¿podría volver a darle forma en una matriz de alguna manera? – mEvans

+1

@mEvans no es para mí! si pego mi código, obtengo la matriz de nuevo ... pero sí, siempre puedes convertir un 'vector' en' matriz' usando 'matriz (mat)'. Eche un vistazo a todos los argumentos opcionales a 'matriz' también. Pero, como dije en mi respuesta, creo que la respuesta de Harlan es mejor por una posibilidad remota. – Justin

56
X[X < .1] <- 0 

(o NA, aunque 0 suena más apropiado en este caso.)

matrices se acaba de vectores con las dimensiones, por lo que puede tratarlos como un vector cuando se asigna a ellos. En este caso, está creando un vector booleano sobre X que indica los valores pequeños, y asigna el lado derecho a cada elemento que sea VERDADERO.

+0

¿Puede hacer esto solo en ciertas columnas? Está reemplazando otros valores en otras columnas (como fechas y horas, etc.) cuando lo ejecuto en toda la matriz. – mEvans

+2

Para un subconjunto de cols, puede usar: 'X [, c (1,3,5)] <- apply (X [, c (1,3,5)], 2, function (x) ifelse (x <0.1, 0, x)) '(para las columnas 1, 3 y 5). – jbaums

+7

@mEvans: si tiene diferentes tipos de datos en diferentes columnas, eso significa que probablemente tenga un marco de datos, no una matriz. Estos son diferentes bichos en R, aunque muchas operaciones funcionarán con ambos. Debería verificar cuál es su conjunto de datos antes de hacer cualquier otra cosa, ya que eso probablemente le ahorrará mucho dolor más adelante. –

1

sólo para proporcionar una (en mi opinión) alternativa interesante:

Si tiene que sujetar los valores por lo que son no menor que un valor, se puede usar pmax:

set.seed(42) 
m <- matrix(rnorm(100),10) 

m <- pmax(m, 0) # clamp negative values to 0 

... Sin embargo, esto no funciona en su caso, ya que quiere que los valores < 0.1 se conviertan en 0.

1

Otros métodos equivalentes:

let:

M=matrix(rnorm(10*10), 10, 10) 

La fuerza bruta (educativa)

for (i in 1:nrow(M)) { 
    for (j in 1:ncol(M)) if (M[i,j]<0.1 & !is.na(M[i,j])) M[i,j]=NA 
    } 

Si hay valores perdidos (NA) en M, omitiendo !is.na dará errores.

Otra forma: usando recode en el paquete car:

library(car) 
recode(M, "lo:0.099999=NA") 

No se puede especificar una desigualdad estricta aquí, así que por eso hay un montón de 9. poner más nueves y se convierte en 0,1. lo es una conveniencia de recode, que da el valor mínimo (eliminación de NA).

1

Una solución hoja.de.datos:

if(!require(plyr)){ 
    install.packages("plyr")} 

rm.neg<-colwise(function(x){ 
    return(ifelse(x < 0.1, 0, x))}) 

rm.neg(data.frame(mat)) 

PD: el código de rm.neg se puede extraer y simplifica para que no se necesita una llamada a plyr, que se utiliza para crear la función colwise.

1

Creo que encontrará que 'ifelse' no es una operación vectorial (en realidad funciona como un bucle), por lo que es órdenes de magnitudes más lentas que el vector equivalente. R favorece las operaciones vectoriales, por lo que aplicar, mapply, sapply son rapidísimos para ciertos cálculos.

Conjuntos de datos pequeños, no hay problema, pero si tiene una variedad de 100k de largo o más, puede ir a cocinar una cena de asado antes de que termine por cualquier método que implique un ciclo.

El siguiente código debería funcionar.

Para vectorial

minvalue <- 0 
X[X < minvalue] <- minvalue 

Para trama de datos o matriz.

minvalue <- 0 
n <- 10 #change to whatever. 
columns <- c(1:n) 
X[X[,columns] < minvalue,columns] <- minvalue 

Otro método rápido, a través de funciones Pmax y Pmin, este tapas de entradas entre 0 y 1 y se puede poner una matriz o trama de datos como el primer argumento no hay problemas.

ulbound <- function(v,MAX=1,MIN=0) pmin(MAX,pmax(MIN,v)) 
Cuestiones relacionadas