Sélection uniquement des colonnes numériques d'un bloc de données


189

Supposons que vous ayez un data.frame comme celui-ci:

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

Comment sélectionneriez-vous uniquement les colonnes de x qui sont numériques?

Réponses:


289

EDIT: mis à jour pour éviter l'utilisation de mal avisé sapply.

Puisqu'un bloc de données est une liste, nous pouvons utiliser les fonctions d'application de liste:

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

Puis sous-ensemble standard

x[ , nums]

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

Pour un R moderne plus idiomatique, je recommande maintenant

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

Moins de code, moins reflétant les bizarreries particulières de R, et plus simple et plus robuste à utiliser sur les tables de base de données back-end:

dplyr::select_if(x, is.numeric)

10
x[nums]ou x[sapply(x,is.numeric)]fonctionne aussi bien. Et ils reviennent toujours data.frame. Comparez x[1]vs x[,1]- le premier est data.frame, le second est un vecteur. Si l'on veut empêcher la conversion, il faut utiliser x[, 1, drop=FALSE].
Marek

Un moyen de sélectionner uniquement des données continues? Cette méthode retourne des nombres continus et entiers.
Abandonné

Lorsqu'il n'y a pas de colonne numérique, l'erreur suivante se produit undefined columns selected. Comment l'évitez-vous?
Yohan Obadia

Les données continues @SoilSciGuy doivent être as.numeric. Peut-être avez-vous des données factorielles sous forme numérique? Vous devriez ouvrir une nouvelle question.
Brandon Bertelsen

1
@YohanObadia Vous pouvez utiliser un tryCatch()pour gérer cela. Veuillez envisager d'ouvrir une nouvelle question.
Brandon Bertelsen le

79

La select_if(fonction) du package dplyr est une solution élégante:

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

44

Filter() du package de base est la fonction parfaite pour ce cas d'utilisation: il vous suffit de coder:

Filter(is.numeric, x)

C'est aussi beaucoup plus rapide que select_if():

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

renvoie (sur mon ordinateur) une médiane de 60 microsecondes pour Filter, et 21 000 microsecondes pour select_if(350x plus rapide).


Cette solution n'échoue pas lorsqu'aucune colonne numérique n'est présente. Y a-t-il des inconvénients à l'utiliser?
bli

Le filtre s'applique uniquement aux lignes d'un dataframe plutôt qu'aux colonnes. En tant que telle, cette solution ne donnerait pas le résultat correct.
Michael

4
@Michael ne confondez pas le filtre du package de base et le filtre du package dplyr!
Kevin Zarca

1
@bli Je ne vois aucun inconvénient à utiliser Filter. Son entrée est un objet data.frame et il renvoie un data.frame
Kevin Zarca

Sonnerie ici pour référence: ce Filter()qui ne fonctionne pas ici, c'est le remplacement, par exemple Filter(is.numeric,iris) <- 0.5*Filter(is.numeric,iris)ne fonctionnera pas.
Mobeus Zoom le

8

si vous ne vous intéressez qu'aux noms de colonnes, utilisez ceci:

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

5

Ceci est un code alternatif aux autres réponses:

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

avec un data.table

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

3
Il s'agit plus d'un commentaire sur la réponse sélectionnée que d'une réponse unique.
Brandon Bertelsen

2
Les colonnes peuvent avoir plus d'une classe.
Rich Scriven


2

La bibliothèque PCAmixdata a une fonction splitmix qui divise les données quantitatives (données numériques) et qualitatives (données catégorielles) d'un dataframe donné "YourDataframe" comme indiqué ci-dessous:

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

Une autre façon pourrait être la suivante: -

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

1
Salut Ayushi, cela a probablement été rejeté parce que c'est une répétition de la première réponse, mais cette méthode a quelques problèmes qui ont été identifiés. Jetez un œil aux commentaires dans la première réponse, vous verrez ce que je veux dire.
Brandon Bertelsen

1

Si vous avez de nombreuses variables de facteur, vous pouvez utiliser select_iffuntion. installez les packages dplyr. Il existe de nombreuses fonctions qui séparent les données en satisfaisant une condition. vous pouvez définir les conditions.

Utilisez comme ça.

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

2
On dirait un double de cette réponse précédente stackoverflow.com/a/40808873/170352
Brandon Bertelsen

0

Cela ne répond pas directement à la question mais peut être très utile, surtout si vous voulez quelque chose comme toutes les colonnes numériques à l'exception de votre colonne id et de la variable dépendante.

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))
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.