2012-02-24 14 views
40

Ho una matrice (2601 per 58) di stime di concentrazione di particelle in un modello di qualità dell'aria. Poiché i monitor della qualità dell'aria della vita reale non possono misurare sotto 0,1 ug/L, ho bisogno di sostituire tutti i valori nella mia matrice che sono <0.1 con un valore zero/NA/null.Sostituire tutti i valori in una matrice <0,1 con 0

Qualcuno ha suggerito ifelse(test, true, false) con una frase logica, ma quando lo provo cancella tutto.

+2

La domanda su cosa sostituire con valori negativi o zero è interessante. Poiché così tanti modelli sono costruiti su una base di log (y), spesso li sostituisco con il punto medio tra il limite inferiore del normale e lo zero. (Probabilmente una domanda secondaria posta al meglio su stats.exchange.) –

+0

@Dwin, +1 a quel commento. Mi piacerebbe vedere questa seconda domanda, e le sue risposte su crossvalidated.com –

+0

è un commento interessante- Vedo quello che stai dicendo ... Per il contesto, sto usando questi valori in una regressione con i dati del dipartimento di emergenza (studio epidemiologico della popolazione). La spiegazione che mi è stata data per spiegare perché sostituire <0,1 con 0 era che non vogliamo sovrastimare l'effetto ... qualcosa con "zero inflazionato"? – mEvans

risposta

39

ifelse dovrebbe funzionare:

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

ma vorrei scegliere la risposta di Harlan sulla mia.

mat[mat < 0.1] <- NA 
+0

La cosa con ifelse è che sembra trasformare la mia matrice in un vettore ... sarei in grado di modificarlo in una matrice in qualche modo? – mEvans

+1

@mEvans non fa per me! se incollo il mio codice torno alla matrice ... ma sì, puoi sempre convertire un 'vector' in una' matrice 'usando 'matrix (mat)'. Dai un'occhiata anche a tutti gli argomenti opzionali a 'matrix'. Ma, come ho detto nella mia risposta, penso che la risposta di Harlan sia la cosa migliore da lungo tempo. – Justin

56
X[X < .1] <- 0 

(o NA, pur 0 suoni più appropriato in questo caso.)

matrici sono solo vettori di dimensioni, in modo da poterli trattare come un vettore quando si assegna a loro. In questo caso, stai creando un vettore booleano su X che indica i valori piccoli e assegna il lato destro a ciascun elemento che è VERO.

+0

Puoi farlo solo per determinate colonne? Sostituisce altri valori in altre colonne (come date e ore, ecc.) Quando lo eseguo su tutta la matrice. – mEvans

+2

Per un sottoinsieme di colonne, è possibile utilizzare: 'X [, c (1,3,5)] <- applica (X [, c (1,3,5)], 2, funzione (x) ifelse (x <0.1, 0, x)) '(per le colonne 1, 3 e 5). – jbaums

+7

@mEvans: se si hanno diversi tipi di dati in colonne diverse, ciò significa che probabilmente si dispone di un frame di dati, non di una matrice. Questi sono diversi critters in R, anche se molte operazioni funzioneranno con entrambi. Dovresti controllare qual è il set di dati prima di fare qualsiasi altra cosa, poiché probabilmente questo ti farà risparmiare molto tempo dopo. –

1

solo per fornire un (a mio parere) interessante alternativa:

Se è necessario bloccare i valori in modo che siano mai più piccolo di un valore, è possibile utilizzare pmax:

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

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

... Questo non funziona nel tuo caso anche se vuoi che i valori < 0.1 diventino 0.

1

Altri metodi equivalenti:

let:

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

forza 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 
    } 

Se ci sono valori mancanti (NA) in M, omettendo !is.na darà errori.

Un altro modo: usando recode nel pacchetto car:

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

non può specificare una disuguaglianza rigorosa qui, quindi è per questo che c'è un gruppo di 9. mettere più festa e si trasforma in 0.1. lo è una comodità di ricodifica, che fornisce il valore minimo (rimozione di NA).

1

Una soluzione data.frame:

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

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

rm.neg(data.frame(mat)) 

PS: il codice per rm.neg può essere estratto e semplificato in modo da non avere bisogno di una chiamata a plyr, che viene utilizzato per creare la funzione colwise.

1

Penso che scoprirai che "ifelse" non è un'operazione vettoriale (in realtà si comporta come un ciclo), e quindi gli ordini di grandezza sono più lenti del vettore equivalente. R favorisce le operazioni vettoriali, che è il motivo per cui applicare, mapply, sapply è un fulmine veloce per determinati calcoli.

Dataset di piccole dimensioni, non è un problema, ma se si dispone di un array di lunghezza pari o superiore a 100k, è possibile andare a cucinare una cena arrosto prima che termini con un ciclo qualsiasi.

Il seguente codice dovrebbe funzionare.

Per vettore

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

Per dataframe o Matrix.

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

altro metodo veloce, con funzioni Pmax e Pmin, questa caps voci tra 0 e 1 e si può mettere una matrice o dataframe come primo argomento senza problemi.

ulbound <- function(v,MAX=1,MIN=0) pmin(MAX,pmax(MIN,v)) 
Problemi correlati