R: проблема с лексическим ограничением при создании функции с аргументом с многоточием - PullRequest
0 голосов
/ 01 марта 2019

Я сделал много таблиц частот в R и работал над написанием своей собственной функции быстрой таблицы частот (qft), когда столкнулся с тем, что я считаю проблемой лексического определения объема.Вот версия моей функции, которая не работает

library("tidyverse")

data(mtcars)

qft_bad<-function(data,...){
  ft<-data.frame(with(data, table(...)))
  ft<-ft[ft$Freq!=0,]
  return(ft)
}

tst_bad<-qft_bad(mtcars,cyl,gear)

Вы заметите, что если вы попытаетесь запустить qft_bad () , то ошибка "Ошибка" в таблице (...): объект 'cyl' not found "произведен.В качестве обходного пути я написал следующую функцию, которая дает желаемый результат, но требует немного других входных данных.

qft_good<-function(data,...){
      nmes<-c(...)
      vars<-dplyr::select(data,...)
      ft<-data.frame(table(vars))
      ft<-ft[ft$Freq!=0,]
      colnames(ft)[1:length(nmes)]<-nmes
      return(ft)
}

tst_good<-qft_good(mtcars,"cyl","gear")

Я предполагаю, qft_bad () не работает, потому что R пытаетсяоцените аргументы вне входного набора данных, но я немного неясен относительно специфики этой проблемы (есть ли проблема с with () функцией?).

Поскольку qft_good () работает достаточно хорошо для моих целей, я в основном задаю этот вопрос для моего собственного R Просветления.Кто-нибудь может дать лучшее объяснение того, что происходит в моей функции qft_bad () , или создать версию функции qft, которая не требует перечисления имен переменных в кавычках (как вы должны в qft_good () )

1 Ответ

0 голосов
/ 01 марта 2019

Вы можете использовать выражения из rlang для захвата аргументов в ..., а затем без кавычек объединить их в select вызов:

library(tidyverse)
library(rlang)

qft <- function(data, ...){
  args <- enquos(...)
  vars <- select(data, !!!args)
  ft <- data.frame(table(vars))
  ft[ft$Freq != 0, ]
}

qft(mtcars, cyl, gear)
#  cyl gear Freq
#1   4    3    1
#2   6    3    2
#3   8    3   12
#4   4    4    8
#5   6    4    4
#7   4    5    2
#8   6    5    1
#9   8    5    2
...