Auswählen nur numerischer Spalten aus einem Datenrahmen

189

Angenommen, Sie haben einen data.frame wie folgt:

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

Wie würden Sie nur die Spalten in x auswählen, die numerisch sind?

Brandon Bertelsen
quelle

Antworten:

288

BEARBEITEN: aktualisiert, um die Verwendung von schlecht beratenen zu vermeiden sapply.

Da ein Datenrahmen eine Liste ist, können wir die Listenanwendungsfunktionen verwenden:

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

Dann Standard-Teilmenge

x[ , nums]

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

Für ein idiomatischeres modernes R würde ich jetzt empfehlen

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

Weniger Codey, weniger Reflexion der besonderen Macken von R und unkomplizierter und robuster für Datenbank-Back-Ended-Tibbles:

dplyr::select_if(x, is.numeric)
mdsumner
quelle
10
x[nums]oder x[sapply(x,is.numeric)]funktioniert auch. Und sie kehren immer zurück data.frame. Vergleiche x[1]vs x[,1]- erstens ist data.frame, zweitens ist ein Vektor. Wenn man eine Konvertierung verhindern will, muss man verwenden x[, 1, drop=FALSE].
Marek
Gibt es eine Möglichkeit, nur fortlaufende Daten auszuwählen? Diese Methode gibt sowohl stetig als auch ganzzahlig zurück.
Verfallen
Wenn keine numerische Spalte vorhanden ist, tritt der folgende Fehler auf undefined columns selected. Wie vermeidest du das?
Yohan Obadia
@SoilSciGuy kontinuierliche Daten sollten as.numerisch sein. Vielleicht haben Sie Faktordaten in numerischer Form? Sie sollten eine neue Frage öffnen.
Brandon Bertelsen
1
@YohanObadia Sie können ein verwenden, tryCatch()um damit umzugehen. Bitte erwägen Sie, eine neue Frage zu öffnen.
Brandon Bertelsen
79

Die Funktion des dplyr-Pakets select_if(ist eine elegante Lösung:

library("dplyr")
select_if(x, is.numeric)
Sharon
quelle
43

Filter() aus dem Basispaket ist die perfekte Funktion für diesen Anwendungsfall: Sie müssen einfach codieren:

Filter(is.numeric, x)

Es ist auch viel schneller als select_if():

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

gibt (auf meinem Computer) einen Median von 60 Mikrosekunden für Filterund 21 000 Mikrosekunden für select_if(350x schneller) zurück.

Kevin Zarca
quelle
Diese Lösung schlägt nicht fehl, wenn keine numerischen Spalten vorhanden sind. Gibt es irgendwelche Nachteile bei der Verwendung?
bli
Der Filter gilt nur für Zeilen eines Datenrahmens und nicht für Spalten. Daher würde diese Lösung nicht das richtige Ergebnis liefern.
Michael
4
@Michael verwechseln Sie nicht Filter aus dem Basispaket und Filter aus dem dplyr-Paket!
Kevin Zarca
1
@bli Ich sehe keinen Nachteil bei der Verwendung von Filter. Seine Eingabe ist ein data.frame-Objekt und es gibt einen data.frame zurück
Kevin Zarca
Hier nur als Referenz einschalten: Was Filter()hier nicht funktioniert, ist Ersetzen, z Filter(is.numeric,iris) <- 0.5*Filter(is.numeric,iris). B. nicht.
Mobeus Zoom
8

Wenn Sie nur an Spaltennamen interessiert sind, verwenden Sie diese:

names(dplyr::select_if(train,is.numeric))
user3065757
quelle
5

Dies ist ein alternativer Code zu anderen Antworten:

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

mit einer data.table

x[, lapply(x, is.numeric) == TRUE, with = FALSE]
Enrique Pérez Herrero
quelle
3
Dies ist eher ein Kommentar zur ausgewählten Antwort als eine eindeutige Antwort.
Brandon Bertelsen
2
Spalten können mehr als eine Klasse haben.
Rich Scriven
3
library(purrr)
x <- x %>% keep(is.numeric)
Yash Khokale
quelle
2

Die Bibliothek PCAmixdata verfügt über eine Funktion splitmix, die quantitative (numerische Daten) und qualitative (kategoriale Daten) eines bestimmten Datenrahmens "YourDataframe" wie unten gezeigt aufteilt:

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)
user1
quelle
2

Ein anderer Weg könnte wie folgt sein:

#extracting numeric columns from iris datset
(iris[sapply(iris, is.numeric)])
Ayushi
quelle
1
Hallo Ayushi, dies wurde wahrscheinlich abgelehnt, weil es eine Wiederholung der ersten Antwort ist, aber diese Methode hat einige Probleme, die identifiziert wurden. Schauen Sie sich die Kommentare in der ersten Antwort an, Sie werden sehen, was ich meine.
Brandon Bertelsen
1

Wenn Sie viele Faktorvariablen haben, können Sie verwenden select_if . Installieren Sie die dplyr-Pakete. Es gibt viele Funktionen, die Daten trennen, indem sie eine Bedingung erfüllen. Sie können die Bedingungen festlegen.

Verwenden Sie so.

categorical<-select_if(df,is.factor)
str(categorical)
서영재
quelle
2
Sieht aus wie ein Duplikat dieser früheren Antwort stackoverflow.com/a/40808873/170352
Brandon Bertelsen
0

Dies beantwortet die Frage nicht direkt, kann jedoch sehr nützlich sein, insbesondere wenn Sie so etwas wie alle numerischen Spalten mit Ausnahme Ihrer ID-Spalte und der abhängigen Variablen möchten.

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))
RJMCMC
quelle