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?

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)

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)

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


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

5

Ini kode alternatif untuk jawaban lain:

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

dengan data.table

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

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


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)

2

Cara lain bisa sebagai berikut: -

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

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)

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))
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.