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.