如何基于数据帧中相邻单元格的值汇总数据

时间:2019-06-23 17:51:31

标签: r dataframe aggregate

我有一个名为siteData的数据框,具有大约40,000行和4列,这里是一个示例。

Uniprot.ID Site Other_Sites
Q8NE71     E403     
Q8NE71     E705     
Q09666     E545     
Q09666     E550     
Q09666     E574     
Q09666     E766     
Q09666     E796    

对于给定的Uniprot.ID,我想将列出的所有站点添加到Other_Sites列中,但相邻的Site列中列出的站点除外。

我已经尝试过这种简单的for循环。我了解如何使用Uniprot.ID访问给定grepl发生的行号,我遇到的麻烦是以这种方式重复编写整个数据集的方式来编写代码。

for (i in 1:nrow(siteData)) {
  siteData$Other_Sites[i] = siteData[which(grepl(siteData$Uniprot.ID[i], 
                             siteData$Uniprot.ID)),2]
}

目前,我的代码仅向Site列添加了一个Other_Sites值,但是对于我的示例数据,我希望它看起来像这样:

Uniprot.ID Site  Other_Sites
Q8NE71     E403    E705 
Q8NE71     E705    E403 
Q09666     E545    E550,E574,E766,E769  
Q09666     E550    E545,E574,E766,E769
Q09666     E574    E545,E550,E766,E769  
Q09666     E766    E545,E550,E574,E769  
Q09666     E796    E545,E550,E574,E766

更多数据放置形式:

structure(list(Uniprot.ID = c("Q8NE71", "Q8NE71", "Q8NE71", "Q8NE71", 
"Q8NE71", "Q8NE71", "Q09666", "Q09666", "Q09666", "Q09666", "Q09666", 
"Q09666", "Q09666", "Q09666", "Q09666", "Q09666", "Q09666", "Q09666", 
"Q09666", "Q09666", "Q09666", "Q09666", "Q09666", "Q09666", "Q09666", 
"Q09666", "Q09666", "Q09666", "Q6P6C2", "E9PB61", "E9PB61"), 
    Site = c("E168", "E282", "E291", "E300", "E403", "E705", 
    "E545", "E550", "E574", "E766", "E796", "E797", "E924", "E1045", 
    "D1169", "E1173", "E1301", "E1422", "E4894", "E5219", "E5458", 
    "E5673", "E5689", "E5702", "E5703", "E5734", "E5755", "E5759", 
    "E50", "E249", "E250"), PMID = c(27256882L, 27256882L, 27256882L, 
    27256882L, 27256882L, 27256882L, 27256882L, 27256882L, 27256882L, 
    27256882L, 27256882L, 27256882L, 27256882L, 27256882L, 27256882L, 
    27256882L, 27256882L, 27256882L, 27256882L, 27256882L, 27256882L, 
    27256882L, 27256882L, 27256882L, 27256882L, 27256882L, 27256882L, 
    27256882L, 27256882L, 27256882L, 27256882L), Other_Sites = c("E20", 
    "E20", "E20", "E20", "E20", "E20", "E545", "E545", "E545", 
    "E545", "E545", "E545", "E545", "E545", "E545", "E545", "E545", 
    "E545", "E545", "E545", "E545", "E545", "E545", "E545", "E545", 
    "E545", "E545", "E545", "E50", "E249", "E249")), row.names = 100:130, class = "data.frame")

2 个答案:

答案 0 :(得分:2)

我们可以summarise 站点并将它们粘贴到每个组中,然后联接两个表以获得所需的输出。

library(dplyr)

df1 %>% 
  group_by(Uniprot.ID) %>% 
  mutate(Other_Sites=paste(Site, collapse=","))

#>   Uniprot.ID Site              Other_Sites
#> 1     Q09666 E545 E545,E550,E574,E766,E796
#> 2     Q09666 E550 E545,E550,E574,E766,E796
#> 3     Q09666 E574 E545,E550,E574,E766,E796
#> 4     Q09666 E766 E545,E550,E574,E766,E796
#> 5     Q09666 E796 E545,E550,E574,E766,E796
#> 6     Q8NE71 E403                E403,E705
#> 7     Q8NE71 E705                E403,E705

reprex package(v0.3.0)于2019-06-23创建

数据:

df1 <-  read.table(text="Uniprot.ID Site
                         Q8NE71     E403     
                         Q8NE71     E705     
                         Q09666     E545     
                         Q09666     E550     
                         Q09666     E574     
                         Q09666     E766     
                         Q09666     E796 ", header=T)

更新:

要解决OP关于空Site条目的后续评论。

library(tidyverse)

df1 %>% 
  group_by(Uniprot.ID) %>% 
  mutate(Other_Sites=paste(unique(Site), collapse=",")) %>%
  mutate(Other_Sites=gsub("^,*|(?<=,),|,*$", "", 
                          str_remove_all(Other_Sites, if_else(Site==""," ", Site)),
                          perl=T))

#>    Uniprot.ID Site              Other_Sites
#> 1      Q8NE71 E403                     E705
#> 2      Q8NE71 E705                     E403
#> 3      Q09666 E545      E550,E574,E766,E796
#> 4      Q09666 E550      E545,E574,E766,E796
#> 5      Q09666 E574      E545,E550,E766,E796
#> 6      Q09666 E766      E545,E550,E574,E796
#> 7      Q09666 E796      E545,E550,E574,E766
#> 8      Q09666      E545,E550,E574,E766,E796
#> 9      Q09666 E796      E545,E550,E574,E766
#> 10     Q09666      E545,E550,E574,E766,E796
#> 11     Q10B12

reprex package(v0.3.0)于2019-06-23创建

示例数据:

df1 <- structure(list(Uniprot.ID = c("Q8NE71", "Q8NE71", "Q09666", "Q09666", 
                                     "Q09666", "Q09666", "Q09666", "Q09666",
                                     "Q09666", "Q09666", "Q10B12"), 
                      Site = c("E403", "E705", "E545", "E550", "E574", "E766",
                               "E796", "", "E796", "", "")), 
                 row.names = c(NA, -11L), class = "data.frame")

df1
#>    Uniprot.ID Site
#> 1      Q8NE71 E403
#> 2      Q8NE71 E705
#> 3      Q09666 E545
#> 4      Q09666 E550
#> 5      Q09666 E574
#> 6      Q09666 E766
#> 7      Q09666 E796
#> 8      Q09666     
#> 9      Q09666 E796
#> 10     Q09666     
#> 11     Q10B12

答案 1 :(得分:1)

仅通过使用joinssetdiff就能做到的时候,我不太理解为什么在接受的答案中需要paste

输入

df1 <-  read.table(text="Uniprot.ID Site
                         Q8NE71     E403     
                         Q8NE71     E705     
                         Q09666     E545     
                         Q09666     E550     
                         Q09666     E574     
                         Q09666     E766     
                         Q09666     E796 ", header=T)

代码

df1 %>% group_by(Uniprot.ID) %>%
  mutate(Other_Sites = paste(Site, collapse = ",")) %>%
  rowwise() %>%
  mutate(Other_Sites = paste(setdiff(unlist(strsplit(Other_Sites,",")), Site), collapse = ","))

输出:

Uniprot.ID Site  Other_Sites        
  <fct>      <fct> <chr>              
1 Q8NE71     E403  E705               
2 Q8NE71     E705  E403               
3 Q09666     E545  E550,E574,E766,E796
4 Q09666     E550  E545,E574,E766,E796
5 Q09666     E574  E545,E550,E766,E796
6 Q09666     E766  E545,E550,E574,E796
7 Q09666     E796  E545,E550,E574,E766