2012-05-15 14 views
12

Sto lavorando a un set di dati che include dati della comunità e molte delle colonne (specie) hanno molti zeri. Vorrei poter rilasciare queste colonne per alcune delle analisi che sto facendo, in base alla somma dell'intera colonna. Sono tentato di fare questo con un ciclo for, ma ho sentito che la applicano e funzioni sono meglio quando si sta utilizzando R. Il mio obiettivo è quello di rimuovere tutte le colonne con una somma inferiore a 15. ho utilizzato which() per rimuovere le righe da fattori, ad esempio,Esclusione di colonne da un dataframe in base alle somme delle colonne

September<-which(data$Time_point=="September") 

data<-data[-September,] 

ed i due modi che ho provato colonne rimozione è quello di utilizzare apply():

data<-data[,apply(data,2,function(x)sum(x<=15))] 

e utilizzando un disordinato ciclo for/if else combinata :

for (i in 6:length(data)){ 
    if (sum(data[,i])<=15) 
    data[,i]<-NULL 
    else 
    data[,i]<-data[,i] 
    } 

Nessuno di questi metodi ha funzionato. Sicuramente esiste un modo elegante per sbarazzarsi delle colonne in base a criteri logici?

str(head(data,10)) 
'data.frame': 10 obs. of 23 variables: 
$ Core_num : Factor w/ 159 levels "152","153","154",..: 133 72 70 75 89 85 86 90 95 99 
$ Cage_num : num 0 1 2 3 4 5 6 7 8 9 
$ Treatment : Factor w/ 4 levels "","C","CC","NC": 1 2 2 2 2 2 2 2 2 2 
$ Site  : Factor w/ 10 levels "","B","B07","B08",..: 1 8 8 8 7 7 7 7 9 9 
$ Time_point : Factor w/ 3 levels "","May","September": 1 2 2 2 2 2 2 2 2 2 
$ Spionidae : num 108 0 0 0 0 0 0 0 0 0 
$ Syllidae : num 185 0 0 0 3 8 0 1 4 1 
$ Opheliidae : num 424 0 1 0 0 0 1 1 0 0 
$ Cossuridae : num 164 0 7 3 0 0 0 0 0 0 
$ Sternaspidae: num 214 0 0 6 1 0 11 9 0 0 
$ Sabellidae : num 1154 0 2 2 0 ... 
$ Capitellidae: num 256 1 10 17 0 3 0 0 0 0 
$ Dorvillidae : num 21 1 0 0 0 0 0 0 0 0 
$ Cirratulidae: num 17 0 0 0 0 0 0 0 0 0 
$ Oligochaeta : num 3747 12 41 27 32 ... 
$ Nematoda : num 410 5 4 13 0 0 0 2 2 0 
$ Sipuncula : num 33 0 0 0 0 0 0 0 0 0 
$ Ostracoda : num 335 0 1 0 0 0 0 0 0 0 
$ Decapoda : num 62 0 4 0 1 0 0 0 0 0 
$ Amphipoda : num 2789 75 17 34 89 ... 
$ Copepoda : num 75 0 0 0 0 0 0 0 0 0 
$ Tanaidacea : num 84 0 0 0 1 0 0 0 0 0 
$ Mollusca : int 55 0 4 0 0 0 0 0 0 0 
+1

Sarebbe molto più facile aiutare se hai fornito alcuni dati riproducibili. Ad esempio, l'output di 'str (head (data, 10))' sarebbe probabilmente sufficiente. (Le versioni stampate dei tuoi dati sono generalmente inutili, poiché sono difficili da copiare + incollare in esempi e non forniscono informazioni su come i dati sono _stored_, che può essere cruciale.) – joran

+0

Grazie a @joran. Ho modificato la domanda originale per contenere quell'output. Ci dispiace per l'inconvenienza! – Margaret

risposta

13

Che dire di un semplice sottoinsieme? In primo luogo, creiamo un dato semplice framel

R> dd = data.frame(x = runif(5), y = 20*runif(5), z=20*runif(5)) 

quindi selezionare le colonne in cui la somma è maggiore di 15

R> dd1 = dd[,colSums(dd) > 15] 
R> ncol(dd1) 
[1] 2 

nel set di dati, si desidera solo sottoinsieme colonne 6 in poi, quindi qualcosa come :

##Drop the first five columns 
dd[,colSums(dd[,6:ncol(dd)]) > 15] 

o

#Keep the first six columns 
cols_to_drop = c(rep(TRUE, 5), dd[,6:ncol(dd)]>15) 
dd[,cols_to_drop] 

dovrebbe funzionare.


La parte fondamentale da notare è che nelle parentesi quadre, vogliamo un vettore di Logicals, vale a dire un vettore di TRUE e FALSE. Quindi, se volessi creare sottoinsiemi usando qualcosa di un po 'più complicato, allora crea una funzione che restituisce VERO o FALSO e sottoinsieme come al solito.

3

Si dovrebbe essere in grado di indicizzare il tuo direttamente data.frame con un valore booleano e colSums().Per esempio:

set.seed(123) 
dat <- data.frame(var1 = runif(10), var2 = rnorm(10), var3 = rlnorm(10)) 
colSums(dat) 
#----- 
    var1  var2  var3 
5.782475 1.317914 12.91987 
#Let's set the threshold at 5, so we should get var1 and var3 
> dat[, colSums(dat) > 5] 
#----- 
     var1  var3 
1 0.2875775 5.9709924 
2 0.7883051 1.6451811 
3 0.4089769 0.1399294 
... 

EDIT - per affrontare le colonne non numerici

set.seed(123) 
dat <- data.frame(var1 = runif(10), var2 = rnorm(10), var3 = rlnorm(10), var4 = "notNumeric") 

require(plyr) 
dat[, -which(numcolwise(sum)(dat) < 5)] 

Consolec:/Documents and Settings/charles/desktop/

> dat[, -which(numcolwise(sum)(dat) < 5)] 
     var1  var3  var4 
1 0.2875775 5.9709924 notNumeric 
2 0.7883051 1.6451811 notNumeric 
3 0.4089769 0.1399294 notNumeric 
..... 
+2

Cue l'OP dicendo che non ha funzionato sul proprio set di dati in 3 ... 2 ... 1 ... (guarda le prime 6 colonne del loro frame di dati). – joran

+0

'data [, c (1: 5, colSums (data [, 6: length (data)]> 15])]'. La versione apply sarebbe simile ma penso che 'colSums' sia più veloce. – Justin

+0

@joran - bah , buon punto: senza pensare troppo, questo dovrebbe funzionare 'require (plyr); dat [, -which (numcolwise (sum (dat) Chase

1

Ciò restituire le colonne che non contengono tutti gli zeri inclusi i fattori e le colonne di caratteri (ho letto solo la prima cosa rowchunky dei dati):

Leggi in alcuni dei suoi dati:

dat <- read.table(text=" Core_num Cage_num Treatment Site Time_point Spionidae Nereididae Syllidae Opheliidae 
6  24  1   C M2  May   0   0  0   0 
4  22  2   C M2  May   0   0  0   1 
9  27  3   C M2  May   0   0  0   0 
23  41  4   C M  May   0   0  3   0 
19  37  5   C M  May   0   0  8   0 
20  38  6   C M  May   0   0  0   1", header=T) 

Il codice:

summer <- function(x){ 
    if(is.numeric(x)){ 
     sum(x) > 15 
    } else { 
     TRUE 
    } 
} 

dat[, sapply(dat, summer)] 
Problemi correlati