2015-04-15 19 views
9

Tôi có đối tượng data.table trong R có 9.000 cột. Mã của tôi tính toán các giá trị mới cho tất cả 9.000 cột cùng một lúc và trả về một vectơ các giá trị. Tôi chỉ muốn thay thế hàng trong data.table với tất cả các giá trị cùng một lúc. Trong một đối tượng dataFrame, điều này rất dễ dàng. Tuy nhiên, tôi không thể tìm ra cách để làm việc đó trong một data.table.Cập nhật toàn bộ hàng trong data.table trong R

d <- data.table(q=c(1,2,3,4,5,6,7,8,9), x=rep(c("a","b","c"),each=3), y=c(1,3,6), v=1:9) 
d[q==1, := c(5,5,5,5)] # FAILS 
d[q==1, ] <- c(5,5,5,5) # FAILS 

Bất kỳ ý tưởng nào về cách cập nhật toàn bộ hàng một cách hiệu quả cùng một lúc?

Trả lời

11

Bạn có thể sử dụng names(d) cho LHS, sau đó sử dụng as.list để chuyển đổi vec-tơ vào một danh sách để data.table sẽ hiểu rằng nó cần phải gán mỗi giá trị đến một cột khác nhau thay tất cả các giá trị để mỗi cột.

Bạn cũng đang chuyển đổi character vectơ thành numeric tại đây (cột x), vì vậy data.table sẽ trả về cảnh báo để đảm bảo bạn biết điều đó.

vec <- c(5, 5, 5, 5) 
d[q == 1L, names(d) := as.list(vec)][] 
# q x y v 
# 1: 5 5 5 5 
# 2: 2 a 3 2 
# 3: 3 a 6 3 
# 4: 4 b 1 4 
# 5: 5 b 3 5 
# 6: 6 b 6 6 
# 7: 7 c 1 7 
# 8: 8 c 3 8 
# 9: 9 c 6 9 
0

Điều này cũng có thể được thực hiện bằng cách sử dụng set, ví dụ ở trên (tham chiếu theo số hàng).

set(d, 1L, names(d), as.list(vec)) 

Bạn thể đạt được một số tốc độ sử dụng set thay vào đó, nhưng mất một số lợi thế nếu bạn cần lấy lại số hàng đầu tiên.

# Create large data table 
DT = data.table(col1 = 1:1e5) 
cols = paste0('col', 1:9e3) 
for (col in cols){ DT[, col := 1:1e5, with = F] } 
vec <- rep(5,9e3) 

# Test options 
microbenchmark(
    row_idnx <- DT[,.I[col1 == 1L]], # Retrieve row number 
    set(DT, row_idnx, names(DT), as.list(vec)), 
    DT[col1 == 1L, names(DT) := as.list(vec)] 
) 

Unit: microseconds 
              expr  min  lq  mean median  uq  max neval 
       row_idnx <- DT[, .I[col1 == 1L]] 1255.430 1969.5630 2168.9744 2129.2635 2302.1000 3269.947 100 
    set(DT, row_idnx, names(DT), as.list(vec)) 171.606 207.3235 323.7642 236.6765 274.6515 7725.120 100 
DT[col1 == 1L, `:=`(names(DT), as.list(vec))] 2761.289 2998.3750 3361.7842 3155.8165 3444.6310 13473.081 100 
Các vấn đề liên quan