2015-04-28 22 views
10

ho una matrice:applicare, sapply e lappy ritorno NULL

mat <- matrix(c(0,0,0,0,1,1,1,1,-1,-1,-1,-1), ncol = 4 , nrow = 4) 

e applicare le seguenti funzioni per filtrare le colonne con solo le voci positive, ma per le colonne che hanno valori negativi Vengo NULL . Come posso sopprimere i NULL dall'uscita di lapply, apply e sapply?

> lapply(as.data.frame(mat), function(x) { if(all(x >= 0)){return(x)} }) 
$V1 
[1] 0 0 0 0 

$V2 
[1] 1 1 1 1 

$V3 
NULL 

$V4 
[1] 0 0 0 0 

> sapply(as.data.frame(mat), function(x) { if(all(x >= 0)){return(x)} }) 
$V1 
[1] 0 0 0 0 

$V2 
[1] 1 1 1 1 

$V3 
NULL 

$V4 
[1] 0 0 0 0 


> apply(mat, 2, function(x){if (all(x >= 0)){return(x)}}) 
[[1]] 
[1] 0 0 0 0 

[[2]] 
[1] 1 1 1 1 

[[3]] 
NULL 

[[4]] 
[1] 0 0 0 0 

Grazie per qualsiasi aiuto.

risposta

8

Come su

dd <- as.data.frame(mat) 
dd[sapply(dd,function(x) all(x>=0))] 

?

  • sapply(...) restituisce un vettore logico (in questo caso TRUE TRUE FALSE TRUE) che indica se le colonne hanno tutti i valori non negativi.
  • se utilizzato con un frame di dati (non una matrice), l'indicizzazione a parentesi singola con un vettore logico considera il frame di dati come un elenco (che è) e crea un elenco contenente solo gli elementi specificati.

In alternativa

dd[apply(mat>=0,2,all)] 

In questo caso si usa apply(...,2,...) sulla matrice originale per generare il vettore di indicizzazione logico.

o

mat[,apply(mat>=0,2,all)] 

In questo caso, poiché stiamo indicizzare una matrice usiamo [,logical_vector] per selezionare le colonne.

+1

grazie, ma come mai che funziona anche quando non metti una virgola prima del dolce? – Cauchy

+0

'mat [, colSums (mat> = 0)> 0]' anche – thelatemail

7

Un'altra opzione è quella di Filter il risultato mentre Negate ing NULL s (se si vuole conservarlo in un formato elenco)

Res <- lapply(as.data.frame(mat), function(x) if(all(x >= 0)) x) 
Filter(Negate(is.null), Res) 
# $V1 
# [1] 0 0 0 0 
# 
# $V2 
# [1] 1 1 1 1 
# 
# $V4 
# [1] 0 0 0 0 
+4

o semplicemente farlo in 'Filtro' per iniziare:' Filtro (funzione (x) tutto (x> = 0), as.data.frame (mat)) 'per evitare un loop aggiuntivo (se necessario, puoi usare' as.list' alla fine) – eddi

+0

@eddi nice, non ci ho pensato. –