Почему mutate() и add_column() не принимают одни и те же базовые аргументы?

Часто я хочу добавить новый столбец по определенному индексу; mutate() не имеет простой реализации этого, в то время как add_column() делает это через аргументы .before и .after. Я ожидал, что две функции будут вести себя одинаково в простых настройках, но это не так. Ниже приведено преобразование индекса строки MWE в новую переменную. В документации R не проясняется: почему эти две функции различаются своим базовым синтаксисом?

dat <- as.tibble(matrix(rnorm(1e4), nrow=100))
dat1 <- dat %>% mutate(id=row_number()) # works as expected
dat2 <- dat %>% add_column(id=row_number()) # throws error
dat3 <- dat %>% add_column(id=1:nrow(dat), .before=1) # works, but harder to read

person Travis Gerke    schedule 29.01.2018    source источник
comment
В примерах ?row_number написано row_number can be used with single table verbs without specifying x (for data frames and databases that support windowing). add_row не является глаголом dplyr, поэтому для row_number потребуется параметр (но будьте осторожны, он возвращает ранжирование). Проще: rowid_to_column   -  person alistaire    schedule 29.01.2018
comment
Отличный совет по rowid_to_column - абсолютно поможет с опубликованным вариантом использования; хотя меня по-прежнему интересует более широкий вопрос о кажущемся разрыве между этими двумя аккуратными функциями вселенной.   -  person Travis Gerke    schedule 29.01.2018


Ответы (1)


Если вы изучите код этих двух функций, вы получите некоторые подсказки.

dplyr:: мутировать

function (.data, ...) 
{
    UseMethod("mutate")
}
<environment: namespace:dplyr>

табличка:: add_column

function (.data, ..., .before = NULL, .after = NULL) 
{
    df <- tibble(...)
    if (ncol(df) == 0L) {
        return(.data)
    }
    if (nrow(df) != nrow(.data)) {
        if (nrow(df) == 1) {
            df <- df[rep(1L, nrow(.data)), ]
        }
        else {
            stopc("`.data` must have ", nrow(.data), pluralise_n(" row(s)", 
                nrow(.data)), ", not ", nrow(df))
        }
    }
    extra_vars <- intersect(names(df), names(.data))
    if (length(extra_vars) > 0) {
        stopc(pluralise_msg("Column(s) ", extra_vars), pluralise(" already exist[s]", 
            extra_vars))
    }
    pos <- pos_from_before_after_names(.before, .after, colnames(.data))
    end_pos <- ncol(.data) + seq_len(ncol(df))
    indexes_before <- rlang::seq2(1L, pos)
    indexes_after <- rlang::seq2(pos + 1L, ncol(.data))
    indexes <- c(indexes_before, end_pos, indexes_after)
    .data[end_pos] <- df
    .data[indexes]
}
<environment: namespace:tibble>

Во-первых, вы заметите, что они из двух разных пакетов, хотя оба являются частью tidyverse.

Во-вторых, вы увидите, что mutate использует указанный метод, тогда как add_column представляет собой скорее функцию удобства, написанную на базе r с некоторым rlang магия.

Я не уверен в дорожной карте для любого пакета, однако я уверен, что вы могли бы предложить улучшение, если его еще нет, или разветвить проект и предоставить запрос на включение. Это было бы полезным дополнением.

Обновлять

Это уже поднималось в tidyverse/dplyr и, похоже, находится в стадии разработки. хотя еще не запланировано.

person Kevin Arseneau    schedule 29.01.2018
comment
Любые дальнейшие обновления или любое другое обсуждение, происходящее в дорожной карте функций tibble и функций dplyr? - person Lazarus Thurston; 12.11.2018