如何使用非标准评估NSE评估data.table上的参数? [英] How to use non-standard evaluation NSE to evaluate arguments on data.table?

查看:87
本文介绍了如何使用非标准评估NSE评估data.table上的参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我有以下内容

library(data.table)
cars1 = setDT(copy(cars))
cars2 = setDT(copy(cars))

car_list = list(cars1, cars2)
class(car_list) <- "dd"

`[.dd` <- function(x,...) {
  code = rlang::enquos(...)
  cars1 = x[[1]]
  rlang::eval_tidy(quo(cars1[!!!code]))
}

car_list[,.N, by = speed]

所以我希望通过定义[.dd函数在cars1cars2上执行任意操作,以便使用[数据通过cars1cars2执行我放入...的任何内容.table语法,例如

so I wished to perform arbitrary operations on cars1 and cars2 by defining the [.dd function so that whatever I put into ... get executed by cars1 and cars2 using the [ data.table syntax e.g.

car_list[,.N, by = speed]应该执行以下操作

cars1[,.N, by = speed]
cars2[,.N, by = speed]

我也想要

car_list[,speed*2]

要做

cars1[,speed*2]
cars2[,speed*2]

基本上,[.dd中的...必须接受任意代码.

Basically, ... in [.dd has to accept arbitrary code.

我需要捕获...,所以我尝试执行code = rlang::enquos(...),然后rlang::eval_tidy(quo(cars1[!!!code]))无法正常工作并给出错误

somehow I need to capture the ... so I tried to do code = rlang::enquos(...) and then rlang::eval_tidy(quo(cars1[!!!code])) doesn't work and gives error

[.data.table中的错误(cars1,〜,〜.N,by =〜speed): 参数"i"丢失,没有默认值

Error in [.data.table(cars1, ~, ~.N, by = ~speed) : argument "i" is missing, with no default

推荐答案

第一个基本R选项是substitute(...()),后跟do.call:

First base R option is substitute(...()) followed by do.call:

library(data.table)
cars1 = setDT(copy(cars))
cars2 = setDT(copy(cars))
cars2[, speed := sort(speed, decreasing = TRUE)]

car_list = list(cars1, cars2)
class(car_list) <- "dd"

`[.dd` <- function(x,...) {
  a <- substitute(...()) #this is an alist
  expr <- quote(x[[i]])
  expr <- c(expr, a)
  res <- list()
  for (i in seq_along(x)) {
    res[[i]] <- do.call(data.table:::`[.data.table`, expr)
  }
  res
}

all.equal(
  car_list[,.N, by = speed],
  list(cars1[,.N, by = speed], cars2[,.N, by = speed])
)
#[1] TRUE

all.equal(
  car_list[, speed*2],
  list(cars1[, speed*2], cars2[, speed*2])
)
#[1] TRUE

第二个基本R选项是match.call,修改调用,然后求值(您可以在lm中找到此方法):

Second base R option is match.call, modify the call and then evaluate (you find this approach in lm):

`[.dd` <- function(x,...) {
  thecall <- match.call()
  thecall[[1]] <- quote(`[`)
  thecall[[2]] <- quote(x[[i]])
  res <- list()
  for (i in seq_along(x)) {
    res[[i]] <- eval(thecall)
  }
  res
}

all.equal(
  car_list[,.N, by = speed],
  list(cars1[,.N, by = speed], cars2[,.N, by = speed])
)
#[1] TRUE

all.equal(
  car_list[, speed*2],
  list(cars1[, speed*2], cars2[, speed*2])
)
#[1] TRUE

如果您使用:=,我还没有测试过这些方法是否可以复制深层副本.

I haven't tested if these approaches will make a deep copy if you use :=.

这篇关于如何使用非标准评估NSE评估data.table上的参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆