如何在R中将一列的元素与group_by相交

问题描述

让我们假设,我的数据就像

  group_id    col1
1        1     A,B
2        1     B,C
3        2     A,C
4        2     B,D
5        3     A,D
6        3 A,B,C,D

我想总结/改变 col1,它的元素在同一组内(通过 group_id)相交。我需要的输出就像(如果总结)

  group_id col1
1        1    B
2        2 <NA>
3        3  A,D

或者像这样(如果变异)

  group_id col1
1        1    B
2        1    B
3        2 <NA>
4        2 <NA>
5        3  A,D
6        3  A,D

我可以使用函数 toString 轻松创建联合,但我对如何在输出中包含公共元素感到头疼。基本上 intersect 需要至少两个参数,因此在这里不起作用。

dput(df) 如下

df <-  structure(list(group_id = c(1L,1L,2L,3L,3L),col1 = c("A,B","B,C","A,D",D")),class = "data.frame",row.names = c("1","2","3","4","5","6"))

解决方法

您可以在逗号上拆分 col1 并使用 Reduce + intersect 获取每个 group_id 中的公共值。

library(dplyr)
df %>%
  group_by(group_id) %>%
  summarise(col1 = toString(Reduce(intersect,strsplit(col1,','))))

#  group_id col1  
#*    <int> <chr> 
#1        1 "B"   
#2        2 ""    
#3        3 "A,D"
,

这行得通吗:

library(dplyr)
library(tidyr)
df %>% separate_rows(col1) %>% 
   group_by(group_id,col1) %>% filter(n()>1) %>% 
   distinct() %>% group_by(group_id) %>% summarise(col1 = toString(col1)) %>% 
   right_join(df %>% select(group_id) %>% distinct()) %>% 
   arrange(group_id)
`summarise()` ungrouping output (override with `.groups` argument)
Joining,by = "group_id"
# A tibble: 3 x 2
  group_id col1 
     <int> <chr>
1        1 B    
2        2 NA   
3        3 A,D 
,

使用 dplyrtidyr 的一个选项可能是:

df %>%
 separate_rows(col1) %>%
 count(group_id,col1) %>%
 group_by(group_id) %>%
 summarise(col1 = if_else(all(n == 1),NA_character_,paste(col1[n == 2],collapse = ",")))

  group_id col1 
     <int> <chr>
1        1 B    
2        2 <NA> 
3        3 A,D