2014-10-10 17 views
5

Tôi muốn sửa đổi một tập hợp các cột bên trong một data.table thành các yếu tố. Nếu tôi biết tên của các cột trước, tôi nghĩ điều này sẽ rất đơn giản.Tôi có thể cập nhật một cách lập trình loại tập hợp các cột (thành các yếu tố) trong data.table không?

library(data.table) 
dt1 <- data.table(a = (1:4), b = rep(c('a','b')), c = rep(c(0,1))) 
dt1[,class(b)] 
dt1[,b:=factor(b)] 
dt1[,class(b)] 

Nhưng tôi không, và thay vào đó có một danh sách các tên biến

vars.factors <- c('b','c') 

tôi có thể áp dụng các chức năng yếu tố đối với họ mà không có một vấn đề ...

lapply(vars.factors, function(x) dt1[,class(get(x))]) 
lapply(vars.factors, function(x) dt1[,factor(get(x))]) 
lapply(vars.factors, function(x) dt1[,factor(get(x))]) 

Nhưng tôi không biết cách gán lại hoặc cập nhật cột ban đầu trong bảng dữ liệu.

này thất bại ...

lapply(vars.factors, function(x) dt1[,x:=factor(get(x))]) 
    # Error in get(x) : invalid first argument 

Như thực hiện điều này ...

lapply(vars.factors, function(x) dt1[,get(x):=factor(get(x))]) 
    # Error in get(x) : object 'b' not found 

NB. Tôi đã thử câu trả lời được đề xuất here mà không có bất kỳ may mắn nào.

+0

Looking for này? dt2 = as.data.table (lapply (dt1, factor)) – KFB

Trả lời

12

Có, đây là khá đơn giản:

dt1[, (vars.factors) := lapply(.SD, as.factor), .SDcols=vars.factors] 

Trong LHS (của: = trong j), chúng tôi ghi rõ tên của các cột. Nếu một cột đã tồn tại, cột đó sẽ được cập nhật, nếu không, cột mới sẽ được tạo. Trong RHS, chúng ta lặp qua tất cả các cột trong .SD (viết tắt của S ubset của D ata), và chúng tôi chỉ định các cột mà phải ở trong .SD với lập luận .SDcols.

Theo dõi trên nhận xét:

Lưu ý rằng chúng ta cần phải quấn LHS với () cho nó sẽ được đánh giá và lấy tên cột trong vars.factors biến. Điều này là do chúng tôi cho phép cú pháp

DT[, col := value] 

khi chỉ có một cột để chỉ định, bằng cách chỉ định tên cột làm biểu tượng (không có dấu ngoặc kép), hoàn toàn thuận tiện. Điều này tạo ra một cột có tên là col và gán value cho nó.

Để phân biệt hai trường hợp này nhau, chúng tôi cần (). Gói nó với () là đủ để xác định rằng chúng ta thực sự cần phải nhận được các giá trị trong biến.

+0

Cảm ơn bạn - nó hoạt động. Tôi đã thử điều này 'dt1 [, vars.factors: = lapply (.SD, hàm (x) factor (x)), .SDcols = vars.factors]' trước đây nhưng nó có vẻ làm điều gì đó rất khác. Bất kỳ cơ hội nào bạn có thể giải thích tại sao? – drstevok

+1

Cảm ơn bạn đã giải thích thêm – drstevok

2

Sử dụng khung dữ liệu:

> df1 = data.frame(dt1) 
> df1[,vars.factors] = data.frame(sapply(df1[,vars.factors], factor)) 
> dt1 = data.table(df1) 

> dt1 
    a b c 
1: 1 1 b 
2: 2 2 c 
3: 3 3 b 
4: 4 4 c 

> str(dt1) 
Classes ‘data.table’ and 'data.frame': 4 obs. of 3 variables: 
$ a: int 1 2 3 4 
$ b: Factor w/ 4 levels "1","2","3","4": 1 2 3 4 
$ c: Factor w/ 2 levels "b","c": 1 2 1 2 
- attr(*, ".internal.selfref")=<externalptr> 
+0

Ý tưởng rất hay, nhưng đây không phải là cách để làm điều này. Không có nhu cầu trong 'data.frame' hai lần ở đây. Bạn có thể làm toàn bộ điều trong một dòng, chẳng hạn như 'dt1 [vars.factors] <- lapply (setDF (dt1) [vars.yếu tố], yếu tố); setDT (dt1) ' –

+0

@ DavidArenburg: Giải pháp của bạn là thanh lịch. Tôi đã sử dụng các hàm tối thiểu để có được giải pháp. – rnso

Các vấn đề liên quan