将多个列合并为一个

时间:2018-04-24 14:00:19

标签: r dplyr

我有一个R data.frame(简化案例,实际上有几十个TRUE / FALSE列):

 name = c("ball", "pen", "box") 
 red = c(TRUE, FALSE, FALSE) 
 green = c(TRUE, TRUE, FALSE) 
 blue = c(TRUE, TRUE, FALSE) 
 df = data.frame(name, red, green, blue)

name   red green  blue
1 ball  TRUE  TRUE  TRUE
2  pen FALSE  TRUE  TRUE
3  box FALSE FALSE FALSE

我想将一个列附加到包含标记为TRUE的所有颜色的串联的df中:

name   red green  blue   color
1 ball  TRUE  TRUE  TRUE red,green,blue
2  pen FALSE  TRUE  TRUE green, blue
3  box FALSE FALSE FALSE na

有没有办法在不编写繁琐的ifelse / paste语句的情况下执行此操作?

4 个答案:

答案 0 :(得分:5)

我们可以通过以下方式使用基础R toString

df$color <- apply(df[, -1], 1, function(x) toString(names(df[, -1])[x]));
df;
#  name   red green  blue            color
#1 ball  TRUE  TRUE  TRUE red, green, blue
#2  pen FALSE  TRUE  TRUE      green, blue
#3  box FALSE FALSE FALSE

答案 1 :(得分:1)

在不使用dplyr的情况下,可能有更有效的方法,但您可以使用rowwisedo为每行计算:

rowwise(df) %>% do({
    result = as.data.frame(.)
    result$color = paste(names(result)[result == TRUE], collapse = ',')
    result
})

# Source: local data frame [3 x 5]
# Groups: <by row>
# 
# # A tibble: 3 x 5
#   name  red   green blue  color         
# * <fct> <lgl> <lgl> <lgl> <chr>         
# 1 ball  TRUE  TRUE  TRUE  red,green,blue
# 2 pen   FALSE TRUE  TRUE  green,blue    
# 3 box   FALSE FALSE FALSE "" 

答案 2 :(得分:1)

使用tidyverse(此处tidyr + dplyr)即可:

library(tidyverse)
df %>% gather(,,-1) %>%
  filter(value) %>%
  group_by(name) %>%
  summarise(color=paste(key,collapse=",")) %>%
  right_join(df) # left_join(df,.) to preserve your column order

# # A tibble: 3 x 5
#     name          color   red green  blue
#   <fctr>          <chr> <lgl> <lgl> <lgl>
# 1   ball red,green,blue  TRUE  TRUE  TRUE
# 2    pen     green,blue FALSE  TRUE  TRUE
# 3    box           <NA> FALSE FALSE FALSE

答案 3 :(得分:0)

E.g。这样

library(tidyverse)
df %>% mutate(color = apply(df[, -1], 1, function(x) colnames(df)[-1][x]))

  name   red green  blue            color
1 ball  TRUE  TRUE  TRUE red, green, blue
2  pen FALSE  TRUE  TRUE      green, blue
3  box FALSE FALSE FALSE