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?

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)

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)

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).


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


5

To alternatywny kod do innych odpowiedzi:

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

z data.table

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

3
Jest to raczej komentarz do wybranej odpowiedzi, niż odpowiedź unikalna.
Brandon Bertelsen,

2
Kolumny mogą mieć więcej niż jedną klasę.
Rich Scriven,


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)

2

Innym sposobem może być:

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

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)

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))
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.