Selezione di sole colonne numeriche da un frame di dati


189

Supponiamo di avere un data.frame come questo:

x <- data.frame(v1=1:20,v2=1:20,v3=1:20,v4=letters[1:20])

Come selezioneresti solo quelle colonne in x che sono numeriche?

Risposte:


289

EDIT: aggiornato per evitare l'uso di sconsiderati sapply.

Poiché un frame di dati è un elenco, possiamo usare le funzioni di applicazione dell'elenco:

nums <- unlist(lapply(x, is.numeric))  

Quindi il subsetting standard

x[ , nums]

## don't use sapply, even though it's less code
## nums <- sapply(x, is.numeric)

Per una R moderna più idiomatica, ora consiglierei

x[ , purrr::map_lgl(x, is.numeric)]

Meno codey, meno riflettendo le stranezze particolari di R, e più semplice e robusto da usare su tabelle con back-end di database:

dplyr::select_if(x, is.numeric)

10
x[nums]o x[sapply(x,is.numeric)]funziona pure. E ritornano sempre data.frame. Confronta x[1]vs x[,1]: il primo è data.frame, il secondo è un vettore. Se si desidera impedire la conversione, è necessario utilizzare x[, 1, drop=FALSE].
Marek,

Un modo per selezionare solo dati continui? Questo metodo restituisce un numero intero e continuo.
Abbandonato il

Quando non è presente una colonna numerica, si verifica il seguente errore undefined columns selected. Come lo eviti?
Yohan Obadia,

@SoilSciGuy i dati continui dovrebbero essere as.numeric. Forse hai dati fattoriali in forma numerica? Dovresti aprire una nuova domanda.
Brandon Bertelsen,

1
@YohanObadia Puoi usare a tryCatch()per gestire questo. Si prega di considerare l'apertura di una nuova domanda.
Brandon Bertelsen,

79

La funzione del pacchetto dplyr select_if() è una soluzione elegante:

library("dplyr")
select_if(x, is.numeric)

44

Filter() dal pacchetto base è la funzione perfetta per quel caso d'uso: devi semplicemente codificare:

Filter(is.numeric, x)

È anche molto più veloce di select_if():

library(microbenchmark)
microbenchmark(
    dplyr::select_if(mtcars, is.numeric),
    Filter(is.numeric, mtcars)
)

restituisce (sul mio computer) una mediana di 60 microsecondi per Filtere select_if21000 microsecondi per (350 volte più veloce).


Questa soluzione non fallisce quando non sono presenti colonne numeriche. Ci sono degli svantaggi nell'usarlo?
bli

Il filtro si applica solo alle righe di un frame di dati anziché alle colonne. Come tale, questa soluzione non darebbe il risultato corretto.
Michael,

4
@Michael non confondere Filter dal pacchetto base e filter dal pacchetto dplyr!
Kevin Zarca,

1
@bli Non vedo alcun inconveniente nell'uso di Filter. Il suo input è un oggetto data.frame e restituisce un data.frame
Kevin Zarca,

Basta inserire qui come riferimento: ciò Filter()che non funziona qui sta sostituendo, ad esempio Filter(is.numeric,iris) <- 0.5*Filter(is.numeric,iris)non funzionerà.
Mobeus Zoom del

8

nel caso tu sia interessato solo ai nomi delle colonne, usa questo:

names(dplyr::select_if(train,is.numeric))

5

Questo è un codice alternativo ad altre risposte:

x[, sapply(x, class) == "numeric"]

con un data.table

x[, lapply(x, is.numeric) == TRUE, with = FALSE]

3
Questo è più un commento alla risposta selezionata, piuttosto che una risposta unica.
Brandon Bertelsen,

2
Le colonne possono avere più di una classe.
Rich Scriven,


2

La libreria PCAmixdata ha funzioni splitmix che suddivide quantitativo (dati numerici) e qualitativo (dati categorici) di un determinato frame di dati "YourDataframe" come mostrato di seguito:

install.packages("PCAmixdata")
library(PCAmixdata)
split <- splitmix(YourDataframe)
X1 <- split$X.quanti(Gives numerical columns in the dataset) 
X2 <- split$X.quali (Gives categorical columns in the dataset)

2

Un altro modo potrebbe essere il seguente: -

#extracting numeric columns from iris datset
(iris[sapply(iris, is.numeric)])

1
Ciao Ayushi, questo probabilmente è stato retrocesso perché è una ripetizione della prima risposta, ma questo metodo ha alcuni problemi che sono stati identificati. Dai un'occhiata ai commenti nella prima risposta, vedrai cosa intendo.
Brandon Bertelsen,

1

Se hai molte variabili fattoriali, puoi usare la select_iffunzione. installa i pacchetti dplyr. Esistono molte funzioni che separano i dati soddisfacendo una condizione. puoi impostare le condizioni.

Usa così.

categorical<-select_if(df,is.factor)
str(categorical)

2
Sembra un duplicato di questa precedente risposta stackoverflow.com/a/40808873/170352
Brandon Bertelsen

0

Questo non risponde direttamente alla domanda, ma può essere molto utile, soprattutto se si desidera qualcosa come tutte le colonne numeriche ad eccezione della colonna ID e della variabile dipendente.

numeric_cols <- sapply(dataframe, is.numeric) %>% which %>% 
                   names %>% setdiff(., c("id_variable", "dep_var"))

dataframe %<>% dplyr::mutate_at(numeric_cols, function(x) your_function(x))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.