Trong công việc của tôi, tôi sử dụng để có nhiều bảng (chi tiết khách hàng, hồ sơ giao dịch, v.v.). Là một số trong số chúng rất lớn (hàng triệu hàng), gần đây tôi đã chuyển sang gói data.table
(nhờ Matthew). Tuy nhiên, một số trong số đó là khá nhỏ (vài trăm hàng và 4/5 cột) và được gọi nhiều lần. Do đó, tôi bắt đầu suy nghĩ về chi phí [.data.table
trong truy xuất dữ liệu thay vì đặt giá trị (như đã mô tả rõ ràng trong ?set
, ở đâu, bất kể kích thước của bảng một mục được đặt trong khoảng 2 micro giây (tùy thuộc vào cpu).Thời gian trong việc nhận các elemets đơn lẻ từ các đối tượng data.table và data.frame
Tuy nhiên, dường như không tồn tại tương đương với set
để nhận giá trị từ data.table
biết chính xác hàng và cột. Một loại có thể lặp lại[.data.table
.
library(data.table)
library(microbenchmark)
m = matrix(1,nrow=100000,ncol=100)
DF = as.data.frame(m)
DT = as.data.table(m) # same data used in ?set
> microbenchmark(DF[3450,1] , DT[3450, V1], times=1000) # much more overhead in DT
Unit: microseconds
expr min lq median uq max neval
DF[3450, 1] 32.745 36.166 40.5645 43.497 193.533 1000
DT[3450, V1] 788.791 803.453 813.2270 832.287 5826.982 1000
> microbenchmark(DF$V1[3450], DT[3450, 1, with=F], times=1000) # using atomic vector and
# removing part of DT overhead
Unit: microseconds
expr min lq median uq max neval
DF$V1[3450] 2.933 3.910 5.865 6.354 36.166 1000
DT[3450, 1, with = F] 297.629 303.494 305.938 309.359 1878.632 1000
> microbenchmark(DF$V1[3450], DT$V1[3450], times=1000) # using only atomic vectors
Unit: microseconds
expr min lq median uq max neval
DF$V1[3450] 2.933 2.933 3.421 3.422 40.565 1000 # DF seems still a bit faster (23%)
DT$V1[3450] 3.910 3.911 4.399 4.399 16.128 1000
Phương pháp cuối cùng thực sự là phương pháp tốt nhất để nhanh chóng truy lục một phần tử một vài lần. Tuy nhiên, set
thậm chí còn nhanh hơn
> microbenchmark(set(DT,1L,1L,5L), times=1000)
Unit: microseconds
expr min lq median uq max neval
set(DT, 1L, 1L, 5L) 1.955 1.956 2.444 2.444 24.926 1000
câu hỏi là: nếu chúng ta có thể set
một giá trị trong 2,444 micro nên không thể thực hiện để có được một giá trị trong một khoảng nhỏ hơn (hoặc ít nhất là tương tự) của thời gian? Cảm ơn.
EDIT: bổ sung thêm hai lựa chọn như đề xuất:
> microbenchmark(`[.data.frame`(DT,3450,1), DT[["V1"]][3450], times=1000)
Unit: microseconds
expr min lq median uq max neval
`[.data.frame`(DT, 3450, 1) 46.428 47.895 48.383 48.872 2165.509 1000
DT[["V1"]][3450] 20.038 21.504 23.459 24.437 116.316 1000
mà tiếc là không phải là nhanh hơn so với những nỗ lực trước đó.
Tôi đồng ý với câu hỏi của bạn rằng chi phí có thể/không nên quá nhiều. Tuy nhiên, để thay đổi, làm thế nào về 'DT [[" V1 "]] [3450]' ?? – Arun
Hoặc sử dụng data.frame subsetting: ''[.data.frame' (DT, 3450,1)' (''' được cho là backticks.) – Roland
Nhưng tôi là một chút hoài nghi về nhu cầu nhận thức của bạn cho subsetting lặp đi lặp lại. Thường thì điều này có nghĩa là bạn có thể tối ưu hóa bằng cách thay đổi thuật toán của mình. – Roland