R - несколько вызовов dplyr :: Crossing () - я могу упростить? - PullRequest
1 голос
/ 16 февраля 2020

У меня есть фрагмент кода:

library(tidyr)
library(dplyr)

df_ref <- data.frame(factor_1 = "A", factor_2 = "Y", factor_3 = "3")

factor_1_levels <- c("A", "B", "C")
factor_2_levels <- c("X", "Y", "Z")
factor_3_levels <- c("1", "2", "3")

df_ref_1 <- crossing(select(df_ref, -factor_1), factor_1_levels) %>% rename(factor_1 = factor_1_levels)
df_ref_2 <- crossing(select(df_ref, -factor_2), factor_2_levels) %>% rename(factor_2 = factor_2_levels)
df_ref_3 <- crossing(select(df_ref, -factor_3), factor_3_levels) %>% rename(factor_3 = factor_3_levels)

Вы можете видеть, что у меня определены 3 фактора, и я делаю то же самое с каждым из них. Код делает то, что мне нужно, но это плохой код. В реальных примерах у меня могло бы быть 200 факторов вместо этого, и выполнение вышеупомянутых 200 раз, очевидно, действительно очень плохо. Есть ли хороший способ кодировать это, используя одну из функций типа apply() или аналогичную?

Спасибо.

1 Ответ

1 голос
/ 16 февраля 2020

Мы можем использовать combn, чтобы создать попарные комбинации имен в list, затем select столбцы из 'df_ref' и создать crossing из list из 'factor_ \ d + _levels objects in map2 and переименовать столбец

library(dplyr)
library(tidyr)
library(purrr)
library(stringr)
lst1 <- combn(rev(names(df_ref)), 2, FUN = function(nm1)
       df_ref %>%
            select(nm1), simplify = FALSE)
imap(mget(ls(pattern = "^factor_\\d+_levels$")), 
        ~ list(.x, .y) ) %>% 
             map2(lst1, ., ~  crossing(.x, !! .y[[2]] := .y[[1]]) %>%
             rename_at(vars(ends_with('levels')), ~ str_remove(., '_levels')))
#[[1]]
# A tibble: 3 x 3
#  factor_3 factor_2 factor_1
#  <fct>    <fct>    <chr>   
#1 3        Y        A       
#2 3        Y        B       
#3 3        Y        C       

#[[2]]
# A tibble: 3 x 3
#  factor_3 factor_1 factor_2
#  <fct>    <fct>    <chr>   
#1 3        A        X       
#2 3        A        Y       
#3 3        A        Z       

#[[3]]
# A tibble: 3 x 3
#  factor_2 factor_1 factor_3
#  <fct>    <fct>    <chr>   
#1 Y        A        1       
#2 Y        A        2       
#3 Y        A        3       
...