如何基于函数参数转换r data.table对象

时间:2018-12-15 10:44:04

标签: r data.table user-defined-functions

我想创建带有2个参数的r函数:

  1. data.table对象
  2. 有关如何向数据表添加新列的说明。这些新的 列是对现有列的转换。

没有包装功能,我可以这样做:

# load data.table library
library(data.table)
# the exsample data set
dt <- data.table(mtcars)

# adding some new columns
dt[, `:=`(disp_plus_hp = disp + hp,
          drat_plus_wt = drat + wt)]

我知道我可以使用eval + parse组合来解决这样的问题:

# load the exsample data set
dt <- data.table(mtcars)

# character vector of length 1 specifying the transformation
column_transformation = '`:=`(disp_plus_hp = disp + hp,
                              drat_plus_wt = drat + wt)'

# define a function that takes data table and the above character
# to transform the data table
dt_transformer <- function(data_table, add_columns)
{
  data_table[, eval(parse(text = add_columns))]
}

# equivalent to dt[, `:=`(disp_plus_hp = disp + hp,drat_plus_wt = drat + wt)]
dt_transformer(data_table = dt, add_columns = column_transformation)

现在,我想改善解决方案的原因有两个:

  1. 我不喜欢将所有转换都指定为一个 字符串,因为它变得非常难以阅读(列表或 每个转换都带有一个元素的字符向量为 很好)
  2. 我对使用解析函数并不感到兴奋

1 个答案:

答案 0 :(得分:1)

基本上,您想要的是一个函数dplyr::mutate,但带有一个:=运算符。我建议您阅读Advanced R书中的non-standart evaluation一章。以下功能必须改进,但基本上可以完成您想要的工作。

dtmutate <- function(dt, ...)
{
  exprs <- lazyeval::dots_capture(...)

  for (i in seq_along(exprs))
  {    
    col  <- names(exprs)[i]
    expr <- exprs[[i]]
    val  <- lazyeval::f_eval(expr, dt)
    dt[, (col) := val]
  }

  dt[]
  return(invisible())
}

library(data.table)
dt <- data.table(a = 1:10, b = 1:10*2)
dtmutate(dt = dt, c = a+b, d = a*b)
dt