Квазиквотация с data.table

Я пытаюсь осмыслить квазиквотацию, чтобы использовать ее вместе с вызовом data.table. Вот пример:

library(data.table)
library(rlang)
dt <- data.table(col1 = 1:10, col2 = 11:20)

dt[, col1]

Если бы я хотел превратить это в функцию, как бы я это сделал? Я пытался:

foo <- function(dt, col) {
  col <- quo(col)

  expr(dt[, !!col1])
}

foo(dt, col1)

Но получите Error in enexpr(expr) : object 'col1' not found. Я предполагаю, что мне не хватает некоторых шагов, поскольку data.table оценивает это иначе, чем dplyr.


person JBGruber    schedule 21.10.2019    source источник
comment
если вам вообще нужно передать символ, а не символ, просто используйте substitute, затем преобразуйте его в символ, затем используйте формат с двойной точкой для подмножества из основной таблицы данных   -  person Onyambu    schedule 21.10.2019
comment
может быть foo <- function(dt, col) dt[, eval(substitute(col))]?   -  person chinsoon12    schedule 22.10.2019


Ответы (2)


Вы хотите записать имя столбца в виде символа с

col <- ensym(col)

а не quo(), а затем используйте

expr(dt[, !!col])

(не col1, которого там не существует), но это просто вернет выражение. Если вы хотите его оценить, вам понадобится

eval_tidy(expr(dt[, !!col]))

Но на самом деле квазинотация лучше всего работает в tidyverse, а не с функциями data.table изначально. Способ "data.table" может быть больше похож на что-то в этом существующем вопросе: Передайте имя столбца в data.table с помощью переменной. data.table очень предпочитает строки символам.

person MrFlick    schedule 21.10.2019
comment
Отлично, спасибо! col1 была опечаткой, но ensym была здесь ключевой :) - person JBGruber; 21.10.2019
comment
Я понимаю, что вы говорите о способе data.table, но связанный ответ, похоже, больше не работает. Я думал о аргументе строки против символов, но у меня было много проблем с использованием with = FALSE, поэтому я хотел в первую очередь изучить квазинотацию. - person JBGruber; 21.10.2019

Вы можете использовать deparse и substitute и использовать аргумент with=FALSE, как в:

foo <- function(dt, col){
  col_str = deparse(substitute(col))
  dt[, col_str, with = F]
}

или вы можете использовать eval и substitute и использовать аргумент data.table по умолчанию with=TRUE, как в:

foo <- function(dt, col){
  col_symb = substitute(col)
  dt[, eval(col_symb)] # by default: with=TRUE
}

В обоих случаях substitute получит имя аргумента, который вы передаете параметру col. В первом случае deparse преобразует это имя в строку, что позволяет нам выбрать его из таблицы data.table с помощью with = FALSE. Во втором случае мы оцениваем (используя eval) имя аргумента в контексте data.table.

person Etienne Kintzler    schedule 21.10.2019
comment
цель - передать символ. не строка - person Onyambu; 21.10.2019
comment
спасибо, но это будет работать только в том случае, если col является строкой, и при более сложных операциях я обнаружил, что есть дополнительные проблемы - person JBGruber; 21.10.2019
comment
Я исправляю свой ответ соответственно - person Etienne Kintzler; 21.10.2019
comment
Сейчас это выглядит многообещающим. Но почему as.symbol вне функции? Это противоречит цели всего квазиквотирования, не так ли? - person JBGruber; 21.10.2019
comment
Хорошо, я думал, что переменная уже была символом, исправляю соответственно. - person Etienne Kintzler; 21.10.2019