【问题标题】:How to summarize data based on value of adjacent cell in a dataframe如何根据数据框中相邻单元格的值汇总数据
【发布时间】:2019-06-23 17:51:31
【问题描述】:

我有一个名为 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 循环。我了解如何使用grepl 访问给定Uniprot.ID 出现的行号,我遇到的问题是以它会为整个数据集重复执行此操作的方式编写代码。

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

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

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")

【问题讨论】:

    标签: r dataframe aggregate


    【解决方案1】:

    我们可以summariseSite 并将它们为每个组粘贴在一起,然后连接两个表以获得所需的输出。

    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 年 6 月 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 条目的后续 cmets。

    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 年 6 月 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
    

    【讨论】:

    • 一个关于这个的问题:你能建议一种方法来忽略空白网站吗?如果网站是空的,Other_Sites 列中只会有一堆逗号,另外,有没有办法合并 Unique() 函数以删除 Other_Sites 列中的重复项。
    • 有没有办法保留没有站点的行,并为 Other_Sites 提供一个空单元格?
    • 由于您的原始代码几乎完全符合我的要求,因此我想以某种方式将独特的功能应用到 Other_Sites 列,这将删除所有多余的逗号和重复的站点
    • @CalvinBarber 查看更新。不是最干净的解决方案,但它有效。如果你想为行本身保留Site(就像我的第一个解决方案一样)你需要用Other_Sites替换str_remove_all(Other_Sites, if_else(Site==""," ", Site))
    • @M-M 您使用joins 有什么原因吗?我只是想了解
    【解决方案2】:

    我不太明白为什么在接受的答案中需要joins,而这可以通过使用setdiffpaste 来完成

    输入

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-11
      相关资源
      最近更新 更多