首页 > 解决方案 > dplyr 为两个因子变量生成全套虚拟交互项

问题描述

假设我有两个因子变量,一个在我的情况下有很多因子(multi.factor),另一个只有两个因子(two.factor),并且它本身是一个虚拟变量。

df <- data.frame(two.factor = rep(c(0,1), 4)) %>%
  mutate(multi.factor = ceiling(row_number()/2))

df

#>   two.factor multi.factor
#> 1          0            1
#> 2          1            1
#> 3          0            2
#> 4          1            2
#> 5          0            3
#> 6          1            3
#> 7          0            4
#> 8          1            4

我如何使用一种dplyr或其他tidyverse方法为这两个变量创建一组虚拟交互项?换句话说,我需要 4 * 1 = 4 个新的虚拟变量,如果two.factor为 1,则为 1,并且multi.factor是交互项中命名的因子,否则为 0。要做到这一点很长的路要走:

df %<>%
  mutate(interact.1 = case_when(multi.factor == 1 & two.factor == 1 ~ 1, TRUE ~ 0)) %>%
  mutate(interact.2 = case_when(multi.factor == 2 & two.factor == 1 ~ 1, TRUE ~ 0)) %>%
  mutate(interact.3 = case_when(multi.factor == 3 & two.factor == 1 ~ 1, TRUE ~ 0)) %>%
  mutate(interact.4 = case_when(multi.factor == 4 & two.factor == 1 ~ 1, TRUE ~ 0))

df
#>   two.factor multi.factor interact.1 interact.2 interact.3 interact.4
#> 1          0            1          0          0          0          0
#> 2          1            1          1          0          0          0
#> 3          0            2          0          0          0          0
#> 4          1            2          0          1          0          0
#> 5          0            3          0          0          0          0
#> 6          1            3          0          0          1          0
#> 7          0            4          0          0          0          0
#> 8          1            4          0          0          0          1

(我还没有制作multi.factortwo.factor实际的因素,我只是使用整数来表示因素水平以保持复制简单。在我的实际数据中,multi.factor是字符串。我怀疑tidyverse解决方案不会关心。)

标签: rdplyrtidyrforcats

解决方案


假设multi.factor是一个因素,您可以使用map为每个级别创建一个新列:

library(tidyverse)

df <- data.frame(two.factor = rep(c(0,1), 4)) %>%
  mutate(multi.factor = as.factor(ceiling(row_number()/2)))

df %>% 
  bind_cols(
    map( levels(df$multi.factor),
         function(x)
           df %>% transmute(!!paste0("interact.",x) := (multi.factor == x) * two.factor)
    )
  )

推荐阅读