我想编写一个使用data.table
包选择数据集的一部分的函数。声明的函数参数是:
dset
),seg.var
),value
)的值。我能够在基础R中编写工作函数:
# Function without data.table
data.select <- function(dset, seg.var, value){
dset.out <- dset[dset[[seg.var]] == value,]
return(dset.out)
}
data.select(iris, "Species", "setosa")
但是,我无法用data.table
包重写它:下面的函数不起作用。
# Function with data.table
data.select.dt <- function(dset, seg.var, value){
dset <- as.data.table(dset)
dset.out <- dset[seg.var == value,]
return(dset.out)
}
data.select.dt(iris, Species, "setosa")
eval(expr,envir,enclos)中的错误:找不到对象'Species'
data.select.dt(iris, "Species", "setosa")
5个cols的空data.table(0行):Sepal.Length,Sepal.Width,Petal.Length,Petal.Width,Species
输入数据集采用data.frame
格式。重写上述给定功能的目标是提高性能。任何帮助将不胜感激。
答案 0 :(得分:2)
检查您的代码:data.table版本中的dset.out <- dset[dset[[seg.var]] == value,]
应该是Species
,这是您原来的。
"Species"
缺少引号,在调用函数时应为Species
。这就是错误消息在工作区中没有对象data.select.dt <- function(dset, seg.var, value){
dset <- as.data.table(dset)
dset.out <- dset[dset[[seg.var]] == value,]
return(dset.out)
}
data.select.dt(iris, "Species", "setosa")
的原因。
这很有效。
Controllers
DashboardController
Models
BarGaugeModel
CircularGaugeModel
Views
Components
BarGauge
CircularGauge
DashboardView
ViewModels
DashboardViewModel
Main
Main
编辑添加提示,在函数外部进行调试,这样就可以看到事情正在发生的地方。
答案 1 :(得分:2)
评论有点太长了,所以单独回答:
首先,我提到的get()
函数是对@ R.S的评论。回答:
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评论)。
第二次修改:在515 MB {@David Arenburg的一个(分别有is.data.table
检查,V3
和V4
分别)两个函数的基准上进行基准测试{ {1}}和data.table
:
data.frame
如果您同时期待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
显然是合适的。
答案 2 :(得分:1)
这里有一些微妙之处,我的建议是将其分解为几步。首先直接编写代码,然后转换为函数:
您的原始代码在函数之外工作:
require(data.table)
dset <- as.data.table(iris)
dset.out <- dset[Species == "setosa",]
dset.out
> dset <- as.data.table(iris)
> dset.out <- dset[Species == "setosa",]
> dset.out
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1: 5.1 3.5 1.4 0.2 setosa
2: 4.9 3.0 1.4 0.2 setosa
...
然而,当你将它包装在一个函数中失败时......
> require(data.table)
> data.select.dt <- function(dset, seg.var, value){
+ dset <- as.data.table(dset)
+ dset.out <- dset[ seg.var == eval(value) ]
+ return(dset.out)
+ }
> data.select.dt(iris, Species, "setosa")
Show Traceback
Rerun with Debug
Error in eval(expr, envir, enclos) : object 'Species' not found
好的,有趣的是,它为什么在函数调用中失败?您需要正确引用“Species”变量。这需要你在电话中取消引用:
dset[dset[["Species"]] == "setosa",]
> dset[dset[["Species"]] == "setosa",]
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1: 5.1 3.5 1.4 0.2 setosa
2: 4.9 3.0 1.4 0.2 setosa
...
NB。我觉得非常有趣的是调试中的RStudio允许函数工作,但在非调试模式下触发错误。
现在你可以将它包装在一个函数中:
data.select.dt <- function(dset, seg.var, value){
dset <- as.data.table(dset)
dset.out <- dset[dset[[seg.var]] == value,]
return(dset.out)
}
请注意,Species包含在引号"Species"
...
data.select.dt(iris, "Species", "setosa")
data.select.dt(iris, "Species", "setosa")
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1: 5.1 3.5 1.4 0.2 setosa
2: 4.9 3.0 1.4 0.2 setosa
3: 4.7 3.2 1.3 0.2 setosa