Передача двух наборов имен столбцов в функцию - PullRequest
2 голосов
/ 14 июня 2019

Я пытаюсь передать два набора имен столбцов для работы и что-то с ними сделать, используя dplyr.Обычно для одного набора я использовал бы многоточие (...) и конвертировал его в фразы с помощью enquos ().Но теперь у меня есть два набора имен столбцов, поэтому я подумал об использовании списков для их хранения.Как мне сделать эту работу наиболее эффективным способом?(Ответы с использованием функций purrr, rlang и любых других пакетов приветствуются)

Пакеты и пример данных

library(dplyr) #I use whole library(tidyverse) but this is sufficient for this case

some.data <- tibble(col1 = sample(letters[1:3], 500, replace = T),
                    col2 = sample(letters[1:3], 500, replace = T),
                    col3 = sample(letters[4:6], 500, replace = T),
                    col4 = sample(letters[4:6], 500, replace = T))

Моя функция (проще говоря) выглядит следующим образом:

cross_table <- function(data = NULL, list1 = NULL, list2 = NULL){

   for(l1 in list1){
      for(l2 in list2){

         data.out <- data %>% 
            count(l1, l2) %>% 
            spread(l2, n, fill = 0, drop = FALSE)

         print(data.out) #Just to show it works. I want to use 'data.out' object later on

      }
   }
}

и я хочу использовать такую ​​функцию (без указания имен столбцов в виде строк)

some.data %>%
   cross_table(list1 = list(col1, col2), list2 = list(col3, col4))

1 Ответ

3 голосов
/ 14 июня 2019

Здесь вполне подойдет функция vars(). Вы бы использовали его вместо list() в аргументах вашей функции. Я видел пример в этом SO-ответе , и он довольно легко распространяется на вашу ситуацию.

Это плюс некоторый tidyeval в вашем цикле будет выглядеть так:

cross_table <- function(data = NULL, list1 = NULL, list2 = NULL){

        for(l1 in list1){
            for(l2 in list2){

                l1 = enquo(l1)
                l2 = enquo(l2)
                data.out <- data %>%
                    count(!!l1, !!l2) %>%
                    spread(!!l2, n, fill = 0, drop = FALSE) 

                print(data.out) 
            }
        }
    }

some.data %>%
   cross_table(list1 = vars(col1, col2), list2 = vars(col3, col4))


# A tibble: 3 x 4
  col1      d     e     f
  <chr> <dbl> <dbl> <dbl>
1 a        58    61    53
2 b        38    59    47
3 c        65    59    60
# A tibble: 3 x 4
  col1      d     e     f
  <chr> <dbl> <dbl> <dbl>
1 a        53    61    58
2 b        44    47    53
3 c        56    62    66
# A tibble: 3 x 4
  col2      d     e     f
  <chr> <dbl> <dbl> <dbl>
1 a        55    60    51
2 b        57    67    56
3 c        49    52    53
# A tibble: 3 x 4
  col2      d     e     f
  <chr> <dbl> <dbl> <dbl>
1 a        51    56    59
2 b        63    55    62
3 c        39    59    56

Вы также можете использовать alist() вместо list() (что выглядит как Я однажды узнал , но с тех пор забыл :-D).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...