Тидевал в собственных функциях внутри своих функций с трубкой - PullRequest
3 голосов
/ 29 апреля 2019

Итак, я пытаюсь сделать пакет (я не включил мои заголовки roxygen2 ниже):

У меня есть эта функция:

date_from_text <- function(df, x){
  x <- rlang::enquo(x)
  name <- rlang::quo_name(x)

  df %>%
    dplyr::mutate(!!name := lubridate::ymd_hms(!!x))
}

И когда столбец datetime имеет правильный класс, я использую его для извлечения всего компонента.

date_columns <- function(df, x){

  x <- rlang::enquo(x)

  df %>%
      dplyr::mutate(year=lubridate::year(!!x),
           ydag=lubridate::yday(!!x),
           weekday=lubridate::wday(!!x, label=FALSE),
           hour = lubridate::hour(!!x),
           hour_min= hms::as.hms(lubridate::force_tz(!!x)),
           week_num = lubridate::week(!!x),
           month = lubridate::month(!!x),
           date = lubridate::date(!!x))
}

Я не хочу включать функцию date_from_text в NAMESPACE и хочу как-то включить ее в функцию date_columns. Что-то вроде проверки, имеет ли метка времени правильный класс, а если нет, то измените класс ... и затем создайте все компоненты datetime.

Я не знаю, как вызвать первую функцию внутри другой функции.

данные для тестирования:

df <- structure(list(time = c("2018-01-30 20:08:18", "2018-02-01 21:01:25", 
"2018-01-31 23:25:12", "2018-01-28 23:45:34", "2018-01-31 12:00:55", 
"2018-02-04 09:15:31", "2018-01-27 21:08:02", "2018-02-08 01:50:31", 
"2018-02-01 03:15:43", "2018-02-04 01:04:52"), type = c("A", 
"D", "B", "B", "B", "D", "C", "C", "C", "A")), .Names = c("time", 
"type"), row.names = c(NA, -10L), class = c("tbl_df", "tbl", 
"data.frame"))

ОБНОВЛЕНИЕ: Теперь я включил date_from_text в date_columns

date_columns <- function(df, x){
  x <- rlang::enquo(x)

  out <-  df %>%
    date_from_text(!!x) %>%
      dplyr::mutate(year=lubridate::year(!!x),
           ydag=lubridate::yday(!!x),
           weekday=lubridate::wday(!!x, label=FALSE),
           hour = lubridate::hour(!!x),
           hour_min= hms::as.hms(lubridate::force_tz(!!x)),
           week_num = lubridate::week(!!x),
           month = lubridate::month(!!x),
           date = lubridate::date(!!x))
 out

  }

Так что я не понимаю, почему я должен снова использовать !!x внутри date_columns ?? Он уже включен в date_from_text. Я вызываю функцию, а не создаю ее ...

1 Ответ

1 голос
/ 30 апреля 2019

Как выяснилось в комментариях и чате, вопрос не связан ни с разработкой пакетов и пространством имен, ни с конвейером.Вопрос в том, как использовать в возможно вложенных функциях-оболочках.

Ответ заключается в том, что выражения, передаваемые пользователем в функцию, должны заключаться в кавычки и не заключаться в кавычки так же, как в date_from_text() ниже через enquo(x) и !!x.

date_from_text <- function(df, x) {
        x <- rlang::enquo(x)                                  # quote via enquo()
        name <- rlang::quo_name(x) 
        dplyr::mutate(df, !!name := lubridate::ymd_hms(!!x))  # unquote via !!
}

Затем выражения могут передаваться таким функциям в «интерактивном» режиме, как функции dplyr:

date_from_text(df, time)
select(df, time)

Помните, что функции внутри функций принимают не выражения, а выражения, заключенные в кавычки и без кавычек, как в вызове mutate() с enquo(x) и !!x выше.

Это означает, что в date_from_text() ниже оба вызова date_from_text() и mutate() должны получить !!x.

date_columns <- function(df, x) {
        x <- rlang::enquo(x)

        out <- date_from_text(df, !!x)
        out <- dplyr::mutate(out, year = lubridate::year(!!x))
        return(out)
}

Кроме того, при разработке пакета выможет использовать все ваши функции независимо от того, экспортированы они или нет (как я делал с date_from_text() внутри date_columns()).Экспортируемые функции должны быть задокументированы и могут использоваться после установки через library(pkg) или pkg::fun(), тогда как неэкспортированные функции могут использоваться только после установки через pkg:::fun().

Я изменил функции Дэвида вДля того, чтобы сосредоточиться на соответствующих частях .

...