Làm thế nào để bạn xóa một cột theo tên trong data.table?


194

Để thoát khỏi một cột có tên "foo" trong a data.frame, tôi có thể làm:

df <- df[-grep('foo', colnames(df))]

Tuy nhiên, một khi dfđược chuyển đổi thành một data.tableđối tượng, không có cách nào để loại bỏ một cột.

Thí dụ:

df <- data.frame(id = 1:100, foo = rnorm(100))
df2 <- df[-grep('foo', colnames(df))] # works
df3 <- data.table(df)
df3[-grep('foo', colnames(df3))] 

Nhưng một khi nó được chuyển đổi thành một data.tableđối tượng, điều này không còn hoạt động.


2
Việc đặt tên cho dữ liệu sẽ rõ ràng hơn dtthay vì df3...
PatrickT

Câu trả lời:


283

Bất kỳ điều nào sau đây sẽ xóa cột fookhỏi data.table df3:

# Method 1 (and preferred as it takes 0.00s even on a 20GB data.table)
df3[,foo:=NULL]

df3[, c("foo","bar"):=NULL]  # remove two columns

myVar = "foo"
df3[, (myVar):=NULL]   # lookup myVar contents

# Method 2a -- A safe idiom for excluding (possibly multiple)
# columns matching a regex
df3[, grep("^foo$", colnames(df3)):=NULL]

# Method 2b -- An alternative to 2a, also "safe" in the sense described below
df3[, which(grepl("^foo$", colnames(df3))):=NULL]

data.table cũng hỗ trợ cú pháp sau:

## Method 3 (could then assign to df3, 
df3[, !"foo"]  

mặc dù nếu bạn thực sự muốn xóa cột "foo"khỏi df3(thay vì chỉ in chế độ xem của df3cột trừ "foo") thì bạn thực sự muốn sử dụng Phương pháp 1 thay thế.

(Lưu ý rằng nếu bạn sử dụng một phương thức dựa vào grep()hoặc grepl(), bạn cần phải đặt pattern="^foo$"chứ không phải "foo", nếu bạn không muốn các cột có tên như "fool""buffoon"(nghĩa là các cột chứa foodưới dạng chuỗi con) cũng được khớp và xóa.)

Tùy chọn ít an toàn hơn, tốt cho sử dụng tương tác:

Hai thành ngữ tiếp theo cũng sẽ hoạt động - nếu df3chứa kết hợp cột"foo" - nhưng sẽ thất bại theo cách có thể bất ngờ nếu không. Ví dụ: nếu bạn sử dụng bất kỳ tệp nào trong số chúng để tìm kiếm cột không tồn tại "bar", bạn sẽ kết thúc với dữ liệu không có hàng.

Kết quả là, chúng thực sự phù hợp nhất cho việc sử dụng tương tác trong đó người ta có thể, ví dụ, muốn hiển thị một data.table trừ bất kỳ cột nào có tên chứa chuỗi con "foo". Đối với mục đích lập trình (hoặc nếu bạn thực sự muốn xóa (các) cột df3thay vì từ bản sao của nó), Phương thức 1, 2a và 2b thực sự là những lựa chọn tốt nhất.

# Method 4:
df3[, .SD, .SDcols = !patterns("^foo$")]

Cuối cùng, có những cách tiếp cận bằng cách sử dụng with=FALSE, mặc dù data.tableđang dần chuyển sang sử dụng đối số này, vì vậy bây giờ nó không được khuyến khích ở nơi bạn có thể tránh nó; hiển thị ở đây để bạn biết tùy chọn tồn tại trong trường hợp bạn thực sự cần nó:

# Method 5a (like Method 3)
df3[, !"foo", with=FALSE] 
# Method 5b (like Method 4)
df3[, !grep("^foo$", names(df3)), with=FALSE]
# Method 5b (another like Method 4)
df3[, !grepl("^foo$", names(df3)), with=FALSE]

2
Xem bình luận của tôi cho OP về -grepso với !grepl.
Joshua Ulrich

1
@JoshuaUlrich - Điểm tốt. Tôi đã thử ban đầu grepl()và nó không hoạt động, vì các cột data.table không thể được lập chỉ mục bởi một vectơ logic. Nhưng bây giờ tôi nhận ra rằng grepl()có thể được thực hiện để làm việc bằng cách gói nó which(), để nó trả về một vectơ số nguyên.
Josh O'Brien

1
Tôi không biết rằng về lập chỉ mục với data.table, nhưng gói nó vào whichlà thông minh!
Joshua Ulrich

6
Tôi cũng không biết điều đó data.table; đã thêm FR # 1797 . Nhưng, phương pháp 1 là (gần như) nhanh hơn vô hạn so với các phương pháp khác. Phương pháp 1 loại bỏ cột bằng tham chiếu không có bản sao nào cả. Tôi nghi ngờ bạn có được nó trên 0,005 giây cho bất kỳ kích thước dữ liệu nào. Ngược lại, những cái khác có thể hoàn toàn không hoạt động nếu bảng gần 50% RAM vì chúng sao chép tất cả trừ cái cần xóa.
Matt Dowle

1
@ user3969377 nếu bạn muốn xóa một cột dựa trên nội dung của một biến ký tự bạn chỉ cần bọc nó trong ngoặc đơn. I E. df [, (afoo): = NULL]
Dean MacGregor

31

Bạn cũng có thể sử dụng setcho việc này, điều này giúp tránh các chi phí [.data.tabletrong vòng lặp:

dt <- data.table( a=letters, b=LETTERS, c=seq(26), d=letters, e=letters )
set( dt, j=c(1L,3L,5L), value=NULL )
> dt[1:5]
   b d
1: A a
2: B b
3: C c
4: D d
5: E e

Nếu bạn muốn làm điều đó theo tên cột, which(colnames(dt) %in% c("a","c","e"))nên làm việc cho j.


2
Trong data.table1.11.8, nếu bạn muốn làm điều đó bằng tên cột, bạn có thể thực hiện trực tiếp rm.col = c("a","b")dt[, (rm.col):=NULL]
Duccio A

20

Tôi chỉ đơn giản là làm theo kiểu khung dữ liệu:

DT$col = NULL

Hoạt động nhanh và theo như tôi thấy không gây ra vấn đề gì.

CẬP NHẬT: không phải là phương pháp tốt nhất nếu DT của bạn rất lớn, vì sử dụng $<-toán tử sẽ dẫn đến sao chép đối tượng. Vì vậy, sử dụng tốt hơn:

DT[, col:=NULL]

8

Tùy chọn rất đơn giản trong trường hợp bạn có nhiều cột riêng lẻ cần xóa trong bảng dữ liệu và bạn muốn tránh nhập tất cả các tên cột #careadvrated

dt <- dt[, -c(1,4,6,17,83,104)]

Điều này sẽ loại bỏ các cột dựa trên số cột thay thế.

Rõ ràng là nó không hiệu quả vì nó bỏ qua các lợi thế của data.table nhưng nếu bạn làm việc với ít hơn 500.000 hàng thì nó hoạt động tốt


4

Giả dt của bạn có các cột col1, col2, col3, col4, col5,coln .

Để xóa một tập hợp con của chúng:

vx <- as.character(bquote(c(col1, col2, col3, coln)))[-1]
DT[, paste0(vx):=NULL]

đây nên là bình luận
Sachila Ranawaka

-2

Đây là một cách khi bạn muốn đặt # cột thành NULL với tên cột của họ là hàm cho việc sử dụng của bạn :)

deleteColsFromDataTable <- function (train, toDeleteColNames) {

       for (myNm in toDeleteColNames)

       train <- train [,(myNm):=NULL]

       return (train)
}


-7

Đối với data.table, việc gán cột cho NULL sẽ xóa nó:

DT[,c("col1", "col1", "col2", "col2")] <- NULL
^
|---- Notice the extra comma if DT is a data.table

... tương đương với:

DT$col1 <- NULL
DT$col2 <- NULL
DT$col3 <- NULL
DT$col4 <- NULL

Tương đương với data.frame là:

DF[c("col1", "col1", "col2", "col2")] <- NULL
      ^
      |---- Notice the missing comma if DF is a data.frame

H: Tại sao có dấu phẩy trong phiên bản cho data.table và không có dấu phẩy trong phiên bản cho data.frame?

A. Vì data.frames được lưu trữ dưới dạng danh sách các cột, bạn có thể bỏ qua dấu phẩy. Bạn cũng có thể thêm nó vào, tuy nhiên sau đó bạn sẽ cần gán chúng vào danh sách NULLs , DF[, c("col1", "col2", "col3")] <- list(NULL).


@Arun Tôi không thể nghĩ về bất kỳ tình huống nào data.framesmà hàng và cột sẽ được chuyển đổi. Điều đó sẽ là phi logic.
duHaas

@Arun Tôi đã gắn thẻ bạn vì nhận xét đầu tiên của bạn khiến có vẻ như có những lúc bạn có thể gọi DF[column,row]vì vậy tôi chỉ muốn xem liệu thực sự có trường hợp nào xảy ra không.
duHaas

Cập nhật câu trả lời để xóa một lỗi đánh máy.
Contango
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.