Как суммировать данные на основе значения соседней ячейки в кадре данных - PullRequest
0 голосов
/ 23 июня 2019

У меня есть датафрейм под названием siteData с около 40000 строк и 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 ]

2 голосов
/ 23 июня 2019

Мы можем 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

Создано в 2019-06-23 при представлении пакета (v0.3.0)

Данные:

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

Обновление:

Чтобы ответить на последующие комментарии ОП о пустых 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

Создано в 2019-06-23 пакетом представ (v0.3.0)

Пример данных:

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 голос
/ 23 июня 2019

Я не совсем понял, почему в принятом ответе требуется joins, когда это можно сделать, просто используя setdiff и paste

Input

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
...