代码之家  ›  专栏  ›  技术社区  ›  ira

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

  •  0
  • ira  · 技术社区  · 6 年前

    我想创建一个r函数,它有两个参数:

    1. 数据表对象
    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. 我对parse函数的使用不太感兴趣
    1 回复  |  直到 6 年前
        1
  •  1
  •   JRR    6 年前

    基本上你想要的是一个函数 dplyr::mutate 但是有一个 := 操作人员我建议你读一下这本书 non-standart evaluation 高级R书中的章节。以下功能必须改进,但基本上可以完成您想要的工作。

    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