Chỉ chọn các cột số từ khung dữ liệu


189

Giả sử, bạn có một data.frame như thế này:

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

Làm thế nào bạn chỉ chọn những cột trong x là số?

Câu trả lời:


288

EDIT: cập nhật để tránh sử dụng không đúng sapply.

Vì khung dữ liệu là một danh sách, chúng ta có thể sử dụng các hàm áp dụng danh sách:

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

Sau đó, tập hợp con tiêu chuẩn

x[ , nums]

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

Đối với một R hiện đại hơn thành ngữ bây giờ tôi muốn giới thiệu

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

Ít mã hơn, ít phản ánh các quirks cụ thể của R và đơn giản hơn và mạnh mẽ hơn để sử dụng trên các tibble kết thúc cơ sở dữ liệu:

dplyr::select_if(x, is.numeric)

10
x[nums]hoặc x[sapply(x,is.numeric)]làm việc là tốt. Và họ luôn trở về data.frame. So sánh x[1]vs x[,1]- thứ nhất là data.frame, thứ hai là một vectơ. Nếu ai muốn ngăn chặn chuyển đổi thì phải sử dụng x[, 1, drop=FALSE].
Marek

Bất kỳ cách nào để chỉ chọn dữ liệu liên tục? Phương thức này trả về liên tục cũng như số nguyên.
Vô chủ

Khi không có cột số, lỗi sau sẽ phát sinh undefined columns selected. Làm thế nào để bạn tránh nó?
Yohan Obadia

@SoilSciGuy dữ liệu liên tục nên as.numeric. Có lẽ bạn có dữ liệu yếu tố ở dạng số? Bạn nên mở một câu hỏi mới.
Brandon Bertelsen

1
@YohanObadia Bạn có thể sử dụng một tryCatch()để đối phó với điều này. Hãy xem xét việc mở một câu hỏi mới.
Brandon Bertelsen

79

Hàm dplyr của select_if() là một giải pháp tao nhã:

library("dplyr")
select_if(x, is.numeric)

44

Filter() từ gói cơ sở là chức năng hoàn hảo cho trường hợp sử dụng đó: Bạn chỉ cần mã:

Filter(is.numeric, x)

Nó cũng nhanh hơn nhiều so với select_if():

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

trả về (trên máy tính của tôi) trung bình 60 micro giây Filtervà 21 000 micro giây cho select_if(nhanh hơn 350 lần).


Giải pháp này không thất bại khi không có cột số. Có bất kỳ nhược điểm để sử dụng nó?
bli

Bộ lọc chỉ áp dụng cho các hàng của khung dữ liệu thay vì các cột. Như vậy, giải pháp này sẽ không cho kết quả chính xác.
Michael

4
@Michael không nhầm lẫn Bộ lọc từ gói cơ sở và bộ lọc từ gói dplyr!
Kevin Zarca

1
@bli Tôi không thể thấy bất kỳ nhược điểm nào khi sử dụng Bộ lọc. Đầu vào của nó là một đối tượng data.frame và nó trả về data.frame
Kevin Zarca

Chỉ cần vào đây để tham khảo: những gì Filter()không hoạt động ở đây sẽ thay thế, ví dụ như Filter(is.numeric,iris) <- 0.5*Filter(is.numeric,iris)sẽ không hoạt động.
Mobeus Zoom

8

trong trường hợp bạn chỉ quan tâm đến tên cột thì hãy sử dụng:

names(dplyr::select_if(train,is.numeric))

5

Đây là một mã thay thế cho các câu trả lời khác:

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

với một data.table

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

3
Đây là nhiều nhận xét cho câu trả lời được chọn, hơn là câu trả lời aunique.
Brandon Bertelsen

2
Cột có thể có nhiều hơn một lớp.
Rich Scriven


2

Thư viện PCAmixdata có functon splitmix phân tách định lượng (Dữ liệu số) và định tính (Dữ liệu phân loại) của một khung dữ liệu nhất định "YourDataframe" như dưới đây:

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

Một cách khác có thể như sau: -

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

1
Xin chào Ayushi, điều này có lẽ đã bị hạ thấp bởi vì nó lặp lại câu trả lời đầu tiên, nhưng phương pháp này có một số vấn đề đã được xác định. Hãy xem các ý kiến ​​trong câu trả lời đầu tiên, bạn sẽ thấy ý tôi là gì.
Brandon Bertelsen

1

Nếu bạn có nhiều biến nhân tố, bạn có thể sử dụng select_iffuntion. cài đặt các gói dplyr. Có nhiều chức năng phân tách dữ liệu bằng cách thỏa mãn một điều kiện. bạn có thể đặt điều kiện.

Sử dụng như thế này.

categorical<-select_if(df,is.factor)
str(categorical)

2
Trông giống như một bản sao của câu trả lời trước đó stackoverflow.com/a/40808873/170352
Brandon Bertelsen

0

Điều này không trực tiếp trả lời câu hỏi nhưng có thể rất hữu ích, đặc biệt nếu bạn muốn một cái gì đó giống như tất cả các cột số ngoại trừ cột id và biến phụ thuộc.

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))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.