Memilih hanya kolom numerik dari bingkai data

189

Misalkan, Anda memiliki data.frame seperti ini:

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

Bagaimana Anda memilih hanya kolom-kolom dalam x yang numerik?

Brandon Bertelsen
sumber

Jawaban:

289

EDIT: diperbarui untuk menghindari penggunaan yang keliru sapply.

Karena bingkai data adalah daftar, kita dapat menggunakan fungsi daftar-berlaku:

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

Kemudian standar subsetting

x[ , nums]

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

Untuk R modern yang lebih idiomatis sekarang saya sarankan

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

Lebih sedikit kode, kurang mencerminkan keanehan khusus R, dan lebih mudah, dan kuat untuk digunakan pada database-back-ended tibbles:

dplyr::select_if(x, is.numeric)
mdsumner
sumber
10
x[nums]atau x[sapply(x,is.numeric)]berfungsi juga. Dan mereka selalu kembali data.frame. Bandingkan x[1]vs x[,1]- pertama adalah data.frame, kedua adalah vektor. Jika seseorang ingin mencegah konversi maka harus digunakan x[, 1, drop=FALSE].
Marek
Adakah cara untuk memilih data kontinu saja? Metode ini mengembalikan kontinu dan integer.
Derelict
Ketika tidak ada kolom angka, kesalahan berikut muncul undefined columns selected. Bagaimana Anda menghindarinya?
Yohan Obadia
@SoilSciGuy data berkelanjutan harus as.numeric. Mungkin Anda memiliki data faktor yang berbentuk angka? Anda harus membuka pertanyaan baru.
Brandon Bertelsen
1
@YohanObadia Anda dapat menggunakan tryCatch()untuk menangani ini. Silakan pertimbangkan untuk membuka pertanyaan baru.
Brandon Bertelsen
79

Fungsi paket dplyr select_if() adalah solusi yang elegan:

library("dplyr")
select_if(x, is.numeric)
Sharon
sumber
44

Filter() dari paket dasar adalah fungsi yang sempurna untuk kasus penggunaan: Anda hanya perlu kode:

Filter(is.numeric, x)

Ini juga jauh lebih cepat daripada select_if():

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

mengembalikan (di komputer saya) median 60 mikrodetik untuk Filter, dan 21.000 mikrodetik untuk select_if(350x lebih cepat).

Kevin Zarca
sumber
Solusi ini tidak gagal ketika tidak ada kolom numerik. Apakah ada kekurangan untuk menggunakannya?
bli
Filter hanya berlaku untuk baris bingkai data daripada kolom. Dengan demikian, solusi ini tidak akan memberikan hasil yang benar.
Michael
4
@Michael jangan bingung Filter dari paket dasar dan filter dari paket dplyr!
Kevin Zarca
1
@ Bli Saya tidak bisa melihat kekurangan menggunakan Filter. Inputnya adalah objek data.frame dan mengembalikan data.frame
Kevin Zarca
Hanya berdentang di sini untuk referensi: apa yang Filter()tidak berfungsi untuk di sini adalah menggantikan, misalnya Filter(is.numeric,iris) <- 0.5*Filter(is.numeric,iris)tidak akan berfungsi.
Mobeus Zoom
8

jika Anda hanya tertarik pada nama kolom maka gunakan ini:

names(dplyr::select_if(train,is.numeric))
pengguna3065757
sumber
5

Ini kode alternatif untuk jawaban lain:

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

dengan data.table

x[, lapply(x, is.numeric) == TRUE, with = FALSE]
Enrique Pérez Herrero
sumber
3
Ini lebih merupakan komentar untuk jawaban yang dipilih, bukan jawaban yang unik.
Brandon Bertelsen
2
Kolom dapat memiliki lebih dari satu kelas.
Rich Scriven
3
library(purrr)
x <- x %>% keep(is.numeric)
Yash Khokale
sumber
2

Pustaka PCAmixdata memiliki fungsi splitmix yang membagi kuantitatif (data numerik) dan kualitatif (data kategorikal) dari dataframe "YourDataframe" yang diberikan seperti yang ditunjukkan di bawah ini:

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)
pengguna1
sumber
2

Cara lain bisa sebagai berikut: -

#extracting numeric columns from iris datset
(iris[sapply(iris, is.numeric)])
Ayushi
sumber
1
Hai Ayushi, ini mungkin diturunkan karena merupakan pengulangan dari jawaban pertama, tetapi metode ini memiliki beberapa masalah yang diidentifikasi. Lihatlah komentar di jawaban pertama, Anda akan melihat apa yang saya maksud.
Brandon Bertelsen
1

Jika Anda memiliki banyak variabel faktor, Anda dapat menggunakannya select_if funtion. instal paket dplyr. Ada banyak fungsi yang memisahkan data dengan memenuhi suatu kondisi. Anda dapat mengatur kondisinya.

Gunakan seperti ini.

categorical<-select_if(df,is.factor)
str(categorical)
서영재
sumber
2
Sepertinya duplikat dari jawaban sebelumnya ini stackoverflow.com/a/40808873/170352
Brandon Bertelsen
0

Ini tidak langsung menjawab pertanyaan tetapi bisa sangat berguna, terutama jika Anda menginginkan sesuatu seperti semua kolom numerik kecuali untuk kolom id Anda dan variabel dependen.

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
sumber