data.table:在自定义函数

时间:2017-02-28 21:36:09

标签: r function data.table subset

我想编写一个使用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格式。重写上述给定功能的目标是提高性能。任何帮助将不胜感激。

3 个答案:

答案 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检查,V3V4分别)两个函数的基准上进行基准测试{ {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