2015-04-20 12 views
5

Ho un set di dati con variabili numeriche e categoriali con ~ 200.000 righe, ma molte variabili sono costanti (sia numeriche che cat). Sto cercando di creare un nuovo set di dati in cui le variabili length(unique(data.frame$factor))<=1 vengono eliminate. DatiCome eliminare colonne dal frame di dati con meno di 2 livelli unici in R

esempio dato e tentativi finora:

Temp=c(26:30) 
Feels=c("cold","cold","cold","hot","hot") 
Time=c("night","night","night","night","night") 
Year=c(2015,2015,2015,2015,2015) 
DF=data.frame(Temp,Feels,Time,Year) 

penserei un ciclo avrebbe funzionato, ma qualcosa non funziona nel mio 2 di seguito i tentativi. Ho provato:

for (i in unique(colnames(DF))){ 
    Reduced_DF <- DF[,(length(unique(DF$i)))>1] 
} 

Ma ho davvero bisogno di un vettore dei colnames cui lunghezza (unici (DF $ colonne))> 1, così ho provato il seguito, invece, senza alcun risultato.

for (i in unique(DF)){ 
    if (length(unique(DF$i)) >1) 
    {keepvars <- c(DF$i)} 
    Reduced_DF <- DF[keepvars] 
} 

Qualcuno là fuori hanno esperienza con questo tipo di sottoinsiemi/caduta di colonne con meno di un certo livello di conteggio?

+0

Inoltre, alcuni motivi per cui il vostro per i cicli non si lavora: 1) Si sta creando una nuova variabile 'Reduced_DF' in ogni iterazione invece di cambiare l'originale, il che significa che si dimentica dopo ogni ciclo, 2) Non puoi accedere a una colonna con 'DF $ i', avresti bisogno di' DF [[i]] ', 3) l'espressione' DF [ , (length (unique (DF $ i)))> 1] 'sta provando a subset da tutte le colonne, non decidendo se mantenere' i'. –

risposta

10

È possibile scoprire quanti valori unici sono in ogni colonna con:

sapply(DF, function(col) length(unique(col))) 
# Temp Feels Time Year 
# 5  2  1  1 

È possibile utilizzare questo per sottoinsieme delle colonne:

DF[, sapply(DF, function(col) length(unique(col))) > 1] 
# Temp Feels 
# 1 26 cold 
# 2 27 cold 
# 3 28 cold 
# 4 29 hot 
# 5 30 hot 
+0

Sì, e se hai bisogno dei nomi per altri scopi espliciti, qualcosa come: 'nomi (DF) [sapply (DF, funzione (x) lunghezza (unico (x))> 1)]' lo farà. – thelatemail

+2

Oppure 'DF [sapply (DF, funzione (x)! Is.factor (x) | nlevels (x)> 1)]' se vuoi introdurre 'nlevels' - il numero di livelli di un fattore. – lukeA

+0

Oppure 'Filtro (funzione (x) lunghezza (unico (x))> 1, DF)' per un codice più bello. –

3

Un altro modo con data.table

#Convert object to data.table object 
library(data.table) 
setDT(DF) 

#Drop columns 
todrop <- names(DF)[which(sapply(DF,uniqueN)<2)] 
DF[, (todrop) := NULL] 

Un vantaggio di questo metodo è che non fa una copia (che potrebbe essere noi eful quando hai tante colonne quante ne hai).

Se si utilizza data.table 1.9.4, è necessario modificare la seguente:

#Drop columns 
todrop <- names(DF)[which(sapply(DF,function(x) length(unique(x)<2))] 
DF[, (todrop) := NULL] 
+0

Grazie @ Mike.Gahan per il tuo approccio usando 'data.table'. Sono interessato a saperne di più su questo pacchetto e sulle funzionalità, ma sulla mia fine, il codice è stato errato perché "uniqueN" non è stato trovato. Mi sto perdendo qualcosa? – surfhoya

+0

Il mio errore ... 'uniqueN' è implementato su data.table 1.9.5 e l'ultima versione di CRAN è 1.9.4. Se si desidera utilizzare questo metodo, è possibile scaricare 1.9.5 'library (devtools); install_github ("Rdatatable/data.table", build_vignettes = FALSE) ', oppure puoi sostituire' uniqueN' con 'length (unqieu (x))' –

Problemi correlati