的data.table包支持指數和具有良好的語法讀寫:
library(data.table)
dat <- data.table(index = c(3:14,24), variable = c("Pin", "Pout", "Tout", "D", "L", "mu", "R","K","c","omega","alpha","beta","gamma"), value = runif(13))
setindex(dat, index)
setindex(dat, variable)
# read
dat[ index %in% 3:4, value ]
# write
dat[ index %in% 3:4, value := 2:3 ]
要查看該指數是如何工作的,加verbose = TRUE
,像dat[ index %in% 3:4, value := 2:3, verbose = TRUE ]
和讀取vignettes。 (指數在第四個覆蓋。)
基準爲OP的例子
library(microbenchmark)
datDF = data.frame(dat)
n_idx = 2L
idxcol = "variable"
idx = sample(dat[[idxcol]], n_idx)
v = rnorm(length(idx))
e = substitute(idxcol %in% idx, list(idxcol = as.name(idxcol)))
microbenchmark(
DT = dat[eval(e), value := v ],
DF = datDF$value[ datDF[[idxcol]] %in% idx ] <- v
)
# Unit: microseconds
# expr min lq mean median uq max neval
# DT 449.694 473.136 487.17583 481.042 487.0065 1049.193 100
# DF 27.742 30.239 44.21525 36.065 38.4225 854.723 100
所以它實際上更慢。我仍然會用它(在我看來)更好的語法。請注意,dplyr沒有更新行子集的語法。
有了一張大桌子,你會看到逆轉的風向標:
dat = data.table(variable = do.call(paste0, CJ(LETTERS, LETTERS, LETTERS, LETTERS)))
dat[, index := .I ]
dat[, value := rnorm(.N) ]
setindex(dat, index)
setindex(dat, variable)
datDF = data.frame(dat)
n_idx = 2L
idxcol = "variable"
idx = sample(dat[[idxcol]], n_idx)
v = rnorm(length(idx))
e = substitute(idxcol %in% idx, list(idxcol = as.name(idxcol)))
microbenchmark(
DT = dat[eval(e), value := v ],
DF = datDF$value[ datDF[[idxcol]] %in% idx ] <- v
)
# Unit: microseconds
# expr min lq mean median uq max neval
# DT 471.887 492.5545 701.7914 757.766 817.827 1647.582 100
# DF 17387.134 17729.3280 23750.6721 22629.490 25912.309 83057.928 100
注:DF的方式也可以寫datDF$value[ match(idx, datDF[[idxcol]]) ] <- v
,但我看到大約相同的時間。
如果你真的想要一個字符串,你可能需要'data.frame(...,stringsAsFactors = FALSE)'。 – Frank
無論如何,data.table支持使用二進制搜索和很好的語法對多個索引進行有效索引。請參閱http://r-datatable.com但有一點需要注意:它不支持插入或刪除行/記錄。 – Frank
@Frank知道了,謝謝你的提示。我絕對想要一個真正的字符串,所以我相應地更正了我的代碼。 – DeltaIV