对每个可能的列组合进行变换

时间:2018-02-16 01:01:00

标签: r loops dplyr

R newbe在这里,如果这是超级基本的话,请道歉。我有一个二进制变量的数据框:

df<-data.frame(a = c(0,1,0,1,0), b = c(1, 1, 0, 0, 1), c = c(1,0,1,1,0))

我想为我之前存在的列的每个可能组合创建一个列:

library(tidyverse)
df %>% 
mutate(d = case_when(a==1 & b==1 & c==1 ~ 1),
             e = case_when(a==1 & b==1 & c!=1 ~ 1),
             f = case_when(a==1 & b!=1 & c==1 ~ 1),
             g = case_when(a!=1 & b==1 & c==1 ~ 1))

但是我的真实数据集有太多列没有函数或循环。在R中有一个简单的方法吗?

2 个答案:

答案 0 :(得分:1)

首先请注意,do.call(paste0, df)会将您的所有列合并为一个字符串,不管它们是多少:

do.call(paste0, df)
# [1] "011" "110" "001" "101" "010" "011"

然后,您可以使用spread()包中的tidyr为每个列提供自己的列。请注意,您必须添加一个额外的row列,以便它知道将每个行分开(而不是尝试将它们组合在一起)。

# I added a sixth row that copied the first to make the effect clear
df<-data.frame(a = c(0,1,0,1,0,0), b = c(1, 1, 0, 0, 1, 1), c = c(1,0,1,1,0,1))

# this assumes you want `type_` at the start of each new column,
# but you could use a different convention
df %>%
  mutate(type = paste0("type_", do.call(paste0, df)),
         value = 1,
         row = row_number()) %>%
  spread(type, value, fill = 0) %>%
  select(-row)

结果:

  a b c type_001 type_010 type_011 type_101 type_110
1 0 0 1        1        0        0        0        0
2 0 1 0        0        1        0        0        0
3 0 1 1        0        0        1        0        0
4 0 1 1        0        0        1        0        0
5 1 0 1        0        0        0        1        0
6 1 1 0        0        0        0        0        1

答案 1 :(得分:1)

大卫答案的另一种选择,但我认识到这有点尴尬:

df %>% 
 unite(comb, a:c, remove = FALSE) %>% 
 spread(key = comb, value = comb) %>% 
 mutate_if(is.character, funs(if_else(is.na(.), 0, 1)))

#>   a b c 0_0_1 0_1_0 0_1_1 1_0_1 1_1_0
#> 1 0 0 1     1     0     0     0     0
#> 2 0 1 0     0     1     0     0     0
#> 3 0 1 1     0     0     1     0     0
#> 4 1 0 1     0     0     0     1     0
#> 5 1 1 0     0     0     0     0     1