Использование семантики dplyr::select в функции dplyr::mutate

Здесь я пытаюсь ввести семантику dplyr::select() в функцию, предоставляемую dplyr::mutate(). Ниже приведен минимальный пример.

dat <- tibble(class = rep(c("A", "B"), each = 10),
              x = sample(100, 20),
              y = sample(100, 20),
              z = sample(100, 20))

.reorder_rows <- function(...) {
    x <- list(...)
    y <- as.matrix(do.call("cbind", x))
    h <- hclust(dist(y))
    return(h$order)
}

dat %>%
    group_by(class) %>%
    mutate(h_order = .reorder_rows(x, y, z))

##    class     x     y     z h_order
##   <chr> <int> <int> <int>   <int>
## 1      A    85    17     5       1
## 2      A    67    24    35       5
## ...
## 18     B    76     7    94       9
## 19     B    65    39    85       8
## 20     B    49    11   100      10
## 
## Note: function applied across each group, A and B

То, что я хотел бы сделать, это что-то вроде:

dat %>%
    group_by(class) %>%
    mutate(h_order = .reorder_rows(-class))

Причина, по которой это важно, заключается в том, что когда dat имеет гораздо больше переменных, мне нужно иметь возможность исключить группирующие/конкретные переменные из расчета функции.

Я не уверен, как это будет реализовано, но каким-то образом использование семантики выбора в функции .reorder_rows может быть одним из способов решения этой проблемы.


person robert.amezquita    schedule 17.05.2017    source источник
comment
Определенно было больше того, что вы задали в своем вопросе, с точки зрения возможности использовать помощники select непосредственно внутри функции (я думаю, что это как-то связано с окружением).   -  person robert.amezquita    schedule 18.05.2017


Ответы (1)


Для этого конкретного подхода вам, вероятно, следует вложить и удалить (используя tidyr) по классам, а не группировать по ним:

library(tidyr)
library(purrr)

dat %>%
  nest(-class) %>%
  mutate(h_order = map(data, .reorder_rows)) %>%
  unnest()

Между прочим, обратите внимание, что хотя это работает с вашей функцией, вы также можете написать более короткую версию, которая напрямую использует фрейм данных:

.reorder_rows <- function(x) {
  h <- hclust(dist(as.matrix(x)))
  return(h$order)
}
person David Robinson    schedule 17.05.2017
comment
Определенно, в этом случае я думаю, что подход tidyr +map - тот, который следует использовать! [хотя мне все еще любопытно, как избранные помощники могут быть добавлены в пользовательские функции, но, вероятно, это можно обсудить в другом вопросе]. Спасибо! - person robert.amezquita; 18.05.2017