这是一个评论有点太长了,所以一个单独的答案:
首先,我提到为@ R,S注释的get()
功能。回答:
data.select.dt.V1 <- function(dset, seg.var, value){
if(!data.table::is.data.table(dset)) dset <- data.table::as.data.table(dset) # To convert only if needed
dset[get(seg.var) == value,]
}
data.select.dt.V1(iris, 'Species', 'setosa')
然后更data.table
功能,在这里你可以通过第二个参数是一个表达式(当然,在data.table
方式),而不是一个字符串:
data.select.dt.V2 <- function(dset, seg.var, value){
if(!data.table::is.data.table(dset)) dset <- data.table::as.data.table(dset) # To convert only if needed
sv <- substitute(seg.var)
dset[eval(sv) == value,]
}
data.select.dt.V2(iris, Species, 'setosa')
编辑:功能简化和转换测试(感谢@David Arenburg评论)。
第二编辑:基准测试上述两种功能与@大卫Arenburg对515 MB data.table
和data.frame
一个(有和没有is.data.table
检查,V3
和V4
分别地):
data.select.dt.V3 <- function(dset, seg.var, value) data.table::as.data.table(dset)[.(value), on = seg.var]
data.select.dt.V4 <- function(dset, seg.var, value) {
if(!data.table::is.data.table(dset)) dset <- data.table::as.data.table(dset) # To convert only if needed
dset[.(value), on = seg.var]
}
expr min lq mean median uq max neval cld
1 res <- data.select.dt.V1(iris_df, "Species", "setosa") 3.804995 4.585763 4.150130 4.688093 5.320362 3.166503 10 c
2 res <- data.select.dt.V2(iris_df, Species, "setosa") 3.713275 3.827180 3.865347 4.544968 4.753045 3.218075 10 c
3 res <- data.select.dt.V3(iris_df, "Species", "setosa") 1.927947 1.942868 2.167127 2.328364 2.595420 2.159664 10 b
4 res <- data.select.dt.V4(iris_df, "Species", "setosa") 1.987710 2.004497 2.011502 2.280117 2.856847 1.594249 10 b
5 res <- data.select.dt.V1(iris_dt, "Species", "setosa") 2.771223 2.792428 2.501362 2.805796 3.056144 1.883520 10 b
6 res <- data.select.dt.V2(iris_dt, Species, "setosa") 2.830161 2.970071 2.593192 3.123812 3.170884 1.752576 10 b
7 res <- data.select.dt.V3(iris_dt, "Species", "setosa") 1.963530 2.116116 2.059718 2.203265 2.740949 1.768817 10 b
8 res <- data.select.dt.V4(iris_dt, "Species", "setosa") 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 10 a
显然V4
是一个至如果你期望data.frame
和data.table
,如果只有df
是可能的,最快的功能将是V3
。
为什么你要在函数内转换为data.table?您正在创建整个数据集的副本。通过使用'setDT'将其转换为一个''data.table''就更好了。无论哪种方式,我会做一个简单的二进制连接。像'data.select.dt < - 函数(dset,seg.var,value)as.data.table(dset)[。(value),on = seg.var]',然后将其作为data.select运行.dt(iris,“Species”,“setosa”)' –
我想确保其余的代码能够正常工作。由于我使用的数据集大于'iris',因此我想比较“base”子集的性能和'data.table'中实现的性能,而不必强制重写整个代码。 – kaksat
@kaksat,在我的答案中查看'if(!data.table :: is.data.table(dset))',如果'dset'是'data.table',应该节省一些时间和RAM。 –