R dplyr: Thả nhiều cột


96

Tôi có một khung dữ liệu và danh sách các cột trong khung dữ liệu đó mà tôi muốn bỏ. Hãy sử dụng iristập dữ liệu làm ví dụ. Tôi muốn bỏ Sepal.LengthSepal.Widthchỉ sử dụng các cột còn lại. Làm cách nào để thực hiện việc này bằng cách sử dụng selecthoặc select_từ dplyrgói?

Đây là những gì tôi đã thử cho đến nay:

drop.cols <- c('Sepal.Length', 'Sepal.Width')
iris %>% select(-drop.cols)

Lỗi trong -drop.cols: đối số không hợp lệ cho toán tử một ngôi

iris %>% select_(.dots = -drop.cols)

Lỗi trong -drop.cols: đối số không hợp lệ cho toán tử một ngôi

iris %>% select(!drop.cols)

Lỗi trong! Drop.cols: loại đối số không hợp lệ

iris %>% select_(.dots = !drop.cols)

Lỗi trong! Drop.cols: loại đối số không hợp lệ

Tôi cảm thấy như tôi đang thiếu một cái gì đó rõ ràng bởi vì đây có vẻ như là một hoạt động khá hữu ích mà lẽ ra đã tồn tại. Trên Github, ai đó đã đăng một vấn đề tương tự và Hadley nói rằng sử dụng 'lập chỉ mục tiêu cực'. Đó là những gì (tôi nghĩ) tôi đã cố gắng, nhưng vô ích. Bất kỳ đề xuất?

Câu trả lời:


127

Kiểm tra trợ giúp trên select_vars. Điều đó cung cấp cho bạn một số ý tưởng bổ sung về cách làm việc với điều này.

Trong trường hợp của bạn:

iris %>% select(-one_of(drop.cols))

Cảm ơn. Vì một số lý do, điều này hoạt động trên iris, nhưng không hoạt động trên khung dữ liệu thực tế của tôi ( irislà một ví dụ đồ chơi). Khung dữ liệu của tôi chứa 4558 hàng và 147 cột. Thông báo lỗi tôi nhận được là Error in eval(x$expr, data, x$env) : variable names are limited to 10000 bytes. Bất kỳ ý tưởng tại sao điều này có thể xảy ra?
Navaneethan Santhanam

1
À, có vẻ như tôi đã mắc sai lầm. Tôi vô tình sử dụng select_varsthay vì select. Bây giờ nó hoạt động hoàn hảo!
Navaneethan Santhanam

5
Chúng ta phải tìm hiểu về các hàm sẵn có như thế one_ofnào? Trừ khi tôi thiếu thứ gì đó, nó không xuất hiện trong tài liệu gói ( help(package='dplyr')).
geotheory

4
@geotheory, one_of thực sự được ghi lại. xem help(one_of, package = "dplyr"). Ít nhất nó là trong phiên bản gói 0.5.0. Nhưng việc đọc các blog mà Hadley đăng lên sẽ rất hữu ích khi có cập nhật cho một trong các gói của anh ấy. Và một số chức năng được ghi bên trong các chức năng khác. Thật không may, điều đó đòi hỏi phải đọc tất cả tài liệu, điều mà tôi chủ yếu làm khi tôi muốn một cái gì đó không rõ ràng hoặc có thể thực hiện ngay lập tức với chức năng.
phiver

10
Cảm ơn. Làm thế nào để bạn tìm hiểu về các chức năng này ngay từ đầu, về mặt tài liệu?
geotheory

67

cũng cố gắng

## Notice the lack of quotes
iris %>% select (-c(Sepal.Length, Sepal.Width))

5
Tuyệt quá! Thực sự hữu ích khi chúng ta phải giảm các cột bằng cách sao chép-dán tên từ bảng điều khiển.
Pablo Casas

37

Ngoài ra select(-one_of(drop.cols)), còn có một số tùy chọn khác để loại bỏ các cột bằng cách sử dụng select()không liên quan đến việc xác định tất cả các tên cột cụ thể (sử dụng dữ liệu mẫu dplyr starwars để có thêm một số tên cột khác nhau):

starwars %>% 
  select(-(name:mass)) %>%        # the range of columns from 'name' to 'mass'
  select(-contains('color')) %>%  # any column name that contains 'color'
  select(-starts_with('bi')) %>%  # any column name that starts with 'bi'
  select(-ends_with('er')) %>%    # any column name that ends with 'er'
  select(-matches('^f.+s$')) %>%  # any column name matching the regex pattern
  select_if(~!is.list(.)) %>%     # not by column name but by data type
  head(2)

# A tibble: 2 x 2
homeworld species
  <chr>     <chr>  
1 Tatooine  Human  
2 Tatooine  Droid 

select_if(~!is.list(.))tương đương với select_if(is.list(.))?
Jasha

3
Trong trường hợp ~này là cách viết tắt để xác định một hàm ẩn danh, nó không phải là một ký hiệu khác cho không. Ví dụ, hai cái này có nghĩa giống nhau function(x) {!is.list(x)}~!is.list(.). nghĩ ~như viết tắt cho function(.).
SlyFox

8

Hãy cẩn thận với select()hàm, vì nó được sử dụng cả trong gói dplyr và MASS, vì vậy nếu MASS được tải, select () có thể không hoạt động bình thường. Để biết gói nào được tải, hãy nhập sessionInfo()và tìm gói đó trong phần "gói đính kèm khác:". Nếu nó được tải, hãy nhập detach( "package:MASS", unload = TRUE )select()chức năng của bạn sẽ hoạt động trở lại.


12
cách khác, bạn có thể truy cập hàm trực tiếp trong không gian tên gói như vậy dplyr::select().
Triamus

2
Tôi gặp phải vấn đề này quá thường xuyên. Bây giờ tôi thường xác định một hàm mới ở đầu tập lệnh của mình dselect <- dplyr::select().
filups21

5

Chúng ta có thể thử

iris %>% 
      select_(.dots= setdiff(names(.),drop.cols))

Cảm ơn @akrun, điều này hoạt động hoàn hảo. Tuy nhiên, dplyrvới khả năng làm cho các nhiệm vụ phân tích cơ bản dễ đọc và dễ viết, tôi thất vọng rằng giải pháp thực tế trông giống như một giải pháp thay thế.
Navaneethan Santhanam

@NavaneethanSanthanam Trên thực tế, one_ofgiải pháp còn lại là cách để thực hiện. Tôi đã quên điều đó.
akrun

3

Một cách khác là biến đổi các cột không mong muốn thành NULL, điều này tránh các dấu ngoặc đơn được nhúng:

head(iris,2) %>% mutate_at(drop.cols, ~NULL)
#   Petal.Length Petal.Width Species
# 1          1.4         0.2  setosa
# 2          1.4         0.2  setosa

Điều này cũng không đưa ra cảnh báo nếu một cột không có ở đó.
skoz

3

Nếu bạn có một ký tự đặc biệt trong tên cột, selecthoặc select_có thể không hoạt động như mong đợi. Thuộc tính này của dplyrviệc sử dụng ".". Để tham chiếu đến tập dữ liệu trong câu hỏi, dòng sau có thể được sử dụng để giải quyết vấn đề này:

drop.cols <- c('Sepal.Length', 'Sepal.Width')
  iris %>% .[,setdiff(names(.),drop.cols)]

Câu trả lời chỉ có mã không được khuyến khích. Vui lòng cung cấp một số giải thích về cách hoạt động của câu trả lời và nó khác với các câu trả lời hiện tại như thế nào.
Ralf Stubner

Cảm ơn bạn!! Không có giải pháp nào khác ở trên hoạt động vì lý do chính xác này.
Marty999,

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.