Wybieranie tylko kolumn numerycznych z ramki danych

189

Załóżmy, że masz plik data.frame taki jak ten:

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

Jak wybrałbyś tylko te kolumny w x, które są numeryczne?

Brandon Bertelsen
źródło

Odpowiedzi:

289

EDYCJA: zaktualizowano, aby uniknąć użycia niewłaściwego doradztwa sapply.

Ponieważ ramka danych jest listą, możemy użyć funkcji zastosowania listy:

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

Następnie standardowe podzbiór

x[ , nums]

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

Dla bardziej idiomatycznego nowoczesnego R. poleciłbym teraz

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

Mniej kluczowania, mniej odzwierciedlające szczególne dziwactwa R, a także prostsze i solidniejsze w użyciu w bazach danych opartych na bazie danych:

dplyr::select_if(x, is.numeric)
mdsumner
źródło
10
x[nums]lub też x[sapply(x,is.numeric)]działa. I zawsze wracają data.frame. Porównaj x[1]vs x[,1]- po pierwsze data.frame, drugi to wektor. Jeśli chcesz zapobiec konwersji, musisz użyć x[, 1, drop=FALSE].
Marek
W jakikolwiek sposób wybrać tylko ciągłe dane? Ta metoda zwraca ciągłą, jak również całkowitą.
Opuszczony
Gdy nie ma kolumny numerycznej, pojawia się następujący błąd undefined columns selected. Jak tego uniknąć?
Yohan Obadia,
@SoilSciGuy ciągłe dane powinny być jak liczby. Być może masz dane czynnikowe w postaci liczbowej? Powinieneś otworzyć nowe pytanie.
Brandon Bertelsen
1
@YohanObadia Możesz tryCatch()sobie z tym poradzić. Proszę rozważyć otwarcie nowego pytania.
Brandon Bertelsen
79

Funkcja pakietu dplyr select_if() jest eleganckim rozwiązaniem:

library("dplyr")
select_if(x, is.numeric)
Sharon
źródło
44

Filter() z pakietu podstawowego jest idealną funkcją dla tego przypadku użycia: po prostu musisz zakodować:

Filter(is.numeric, x)

Jest także znacznie szybszy niż select_if():

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

zwraca (na moim komputerze) medianę 60 mikrosekund dla Filteri 21 000 mikrosekund dla select_if(350x szybciej).

Kevin Zarca
źródło
To rozwiązanie nie zawiedzie, gdy nie ma kolumn numerycznych. Czy są jakieś wady korzystania z niego?
bli
Filtr dotyczy tylko wierszy ramki danych, a nie kolumn. Jako takie rozwiązanie nie dałoby poprawnego wyniku.
Michael
4
@Michael nie myli Filtruj z pakietu podstawowego i filtruj z pakietu dplyr!
Kevin Zarca
1
@bli Nie widzę żadnych wad korzystania z filtru. Jego wejściem jest obiekt data.frame i zwraca data.frame
Kevin Zarca
Po prostu chichotam tutaj w celach informacyjnych: to, co tu Filter()nie działa, to zamiana, np. Filter(is.numeric,iris) <- 0.5*Filter(is.numeric,iris)Nie zadziała.
Mobeus Zoom
8

jeśli interesują Cię tylko nazwy kolumn, użyj tego:

names(dplyr::select_if(train,is.numeric))
użytkownik3065757
źródło
5

To alternatywny kod do innych odpowiedzi:

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

z data.table

x[, lapply(x, is.numeric) == TRUE, with = FALSE]
Enrique Pérez Herrero
źródło
3
Jest to raczej komentarz do wybranej odpowiedzi, niż odpowiedź unikalna.
Brandon Bertelsen,
2
Kolumny mogą mieć więcej niż jedną klasę.
Rich Scriven,
3
library(purrr)
x <- x %>% keep(is.numeric)
Yash Khokale
źródło
2

Biblioteka PCAmixdata ma funkcję splitmix, która dzieli ilościową (dane liczbowe) i jakościową (dane kategorialne) daną ramkę danych „YourDataframe”, jak pokazano poniżej:

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)
użytkownik1
źródło
2

Innym sposobem może być:

#extracting numeric columns from iris datset
(iris[sapply(iris, is.numeric)])
Ayushi
źródło
1
Cześć Ayushi, to prawdopodobnie zostało odrzucone, ponieważ jest to powtórzenie pierwszej odpowiedzi, ale ta metoda ma pewne zidentyfikowane problemy. Spójrz na komentarze w pierwszej odpowiedzi, zobaczysz, co mam na myśli.
Brandon Bertelsen,
1

Jeśli masz wiele zmiennych czynnikowych, możesz użyć select_iffunkcji funtion. zainstaluj pakiety dplyr. Istnieje wiele funkcji oddzielających dane poprzez spełnienie warunku. możesz ustawić warunki.

Użyj w ten sposób.

categorical<-select_if(df,is.factor)
str(categorical)
서영재
źródło
2
Wygląda jak duplikat wcześniejszej odpowiedzi stackoverflow.com/a/40808873/170352
Brandon Bertelsen
0

To nie odpowiada bezpośrednio na pytanie, ale może być bardzo przydatne, szczególnie jeśli potrzebujesz czegoś takiego jak wszystkie kolumny numeryczne z wyjątkiem kolumny id i zmiennej zależnej.

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
źródło