R — сопоставление комбинаций вложенных значений списка из индекса и возвращаемого значения

#python #r #dataframe #seurat

#python #r #фрейм данных #сера

Вопрос:

Привет, у меня есть два набора данных. Первый — это список генов, связанных с данным кластером (0-7):

 # gene output

Cluster <- rep(0:7, each = 10)

Gene <- c("LMO3", "NEUROD6", "NFIB", "SNAP25", "RTN1", "CPE", "SOX11", "CSRP2", "VAMP2", "ID2", "EMX2", "LHX5-AS1","PEG10",
          "HES1", "TRH", "WLS", "TPBG", "RPS29", "CRABP2", "RSPO3", "RPL17", "RPL7", "PTMA", "RPL36A", "HMGN2", "H2AFZ",
          "NFIB", "PABPC1", "NEUROD6", "HNRNPH1", "PTN", "FABP7", "IGFBP2", "ID4", "C1orf61", "VIM", "RPS27L", "FABP5",
          "SDCBP", "BNIP3", "TCF7L2", "NEFL", "HMGCS1", "GAP43", "GPM6A", "SQLE", "ID4", "MSMO1", "SCOC", "BASP1", "TTR",
          "MEST", "TPBG", "MDK", "TMBIM6", "RCN1", "C8orf59","ID3","PKM", "PTN", "NCOR1", "ELAVL4", "NNAT", "ETFB",
          "STMN2", "TUBA1A", "GNG3", "MALAT1", "SOX4", "TUBB2B", "CRYAB", "GFAP", "CHCHD2", "HOPX", "LGALS1", "SCRG1", "ISG15",
          "AC090498.1", "B2M", "CLU")

df <- data.frame(cbind(Cluster, Gene))
  

Второй — это индекс, который предоставляет аннотации типа ячейки для определенных комбинаций генов:

 # index

Type <- c("Radial Glia", "Excitatory Neuron ", "Inhibitory Neuron","Inhibitory Neuron",
          "IPC","Excitatory Neuron ","Radial Glia","Microglia","IPC","Inhibitory Neuron")

Subtype <- c("early", "Layer IV", "SST-MGE1", "SST-MGE1", "IPC-div2", 
             "Parietal and Temporal", "oRG/Astrocyte", "Microglia", "IPC-new", "MGE2")

Markers <- c("TOP2A AURK HMGB CTNNB1", "PPP1R1B SCN2A RORB CRYM", "DLX6-AS1 DLX1 SST DCX", "ERBB4 SST DLX2 DLX5 DLX6-AS1",
             "CCNB2 NEUROD4 KIF15 PENK HES6 ZFHX4 GLI3", "MEF2C STMN2 FLT ROBO CRYM", "AQP4 GFAP AGT DIO2 IL33",
             "C1QB AIF1 CCL4 C1QC", "CENPK EOMES", "CCK LHX6 SCGN SST")

index <- data.frame(cbind(Type, Subtype, Markers))
  

Я пытаюсь найти конкретные комбинации, обозначенные маркерами, из списка генов в моем df. При обнаружении такого совпадения будут возвращены соответствующие тип и подтип.
Однако есть пара предостережений, которые мне очень сложно понять.

  1. Списки для каждого кластера могут содержать несколько комбинаций маркеров — таким образом, функция должна перебирать каждую комбинацию маркеров итеративно, а не останавливаться при обнаружении первого совпадения.
  2. Процесс сопоставления индексов должен работать с каждым кластером отдельно — т.Е. Проверять гены в кластере 0 на совпадения маркеров и возвращаемый тип / подтип (ы), затем повторять шаги для кластера 1 и т.д.

Данные моего проекта состоят из десятков df-подобных выходных данных, состоящих из различного количества соответствующих кластеров, каждый из которых содержит от сотен до тысяч генов. Я изо всех сил старался искать решения в Интернете, но, к сожалению, я здесь совершенно пустой.

Любая помощь / советы / предложения будут с благодарностью приняты.

Редактировать:

вывод может выглядеть следующим образом:

   Cluster    Gene        Type Subtype
1       0    LMO3 Radial Glia   early
2       0 NEUROD6        <NA>    <NA>
3       0    NFIB        <NA>    <NA>
4       0  SNAP25        <NA>    <NA>
5       0    RTN1        <NA>    <NA>
6       0     CPE        <NA>    <NA>
  

где правильное совпадение добавило бы строку (строки) в df с соответствующим типом и подтипом для каждого кластера, оставив остаток пустым (NAs).

Комментарии:

1. не могли бы вы указать заголовок ожидаемого результата?

2. Спасибо за ваш вопрос! Я уверен, что есть гораздо более элегантные выходные данные, чем это, но даже следующий черновой вывод уже будет делать то, что мне нужно: правильное совпадение (совпадения) добавит строку (строки) в df с соответствующим типом и подтипом для каждого кластера, оставив остаток пустым (NAs). Возможно, было бы полезно добавить столбец, указывающий количество совпадений, но это уже было бы более причудливым, чем минимальный запрос.

3. Включите выходные данные в вопрос

4. Также почему LMO3 имеет тип Radial? Почему не NA? Я не вижу LMO3 в наборе данных индекса

5. Извините! да, имеет смысл. Я добавил его сейчас.

Ответ №1:

Вероятно, есть гораздо более простой способ сделать это, но здесь он с циклом;

 output = data.frame(Cluster=as.character(), Gene=as.character(), Type=as.character(), Subtype=as.character())

for(i in 1:nrow(df)){
  cluster = df[i,1]
  gene = df[i,2]
  type = index[grep(gene, index$Markers),]
  n_types = nrow(type)
  tmp = data.frame(Cluster=rep(cluster,n_types),
                   Gene=rep(gene, n_types), Type=type[,1], Subtype=type[,2])
  output = rbind(output,tmp)
}
  

Ответ №2:

Я предполагаю, что вы хотите аннотировать каждый кластер генов типами из индекса, когда все маркеры для типа присутствуют в пуле генов кластера.

Я также собираюсь использовать некоторые упрощенные наборы данных; два упрощенных типа в индексе:

 library(tidyverse)

index <- bind_rows(
  tibble(type = "AB", subtype = "X", markers = c("A", "B")),
  tibble(type = "BC", subtype = "Y", markers = c("B", "C")),
)

index
#> # A tibble: 4 x 3
#>   type  subtype markers
#>   <chr> <chr>   <chr>  
#> 1 AB    X       A      
#> 2 AB    X       B      
#> 3 BC    Y       B      
#> 4 BC    Y       C
  

И три разных кластера, которые иллюстрируют разные сценарии сопоставления:

 clusters <- bind_rows(
  tibble(cluster = 0, genes = c("A", "B", "C")), # 2 matches
  tibble(cluster = 1, genes = c("B", "C", "D")), # 1 match
  tibble(cluster = 2, genes = c("C", "D", "E")), # No matches
)

clusters
#> # A tibble: 9 x 2
#>   cluster genes
#>     <dbl> <chr>
#> 1       0 A    
#> 2       0 B    
#> 3       0 C    
#> 4       1 B    
#> 5       1 C    
#> 6       1 D    
#> 7       2 C    
#> 8       2 D    
#> 9       2 E
  

Я бы подошел к этому, сначала создав функцию, которая возвращает совпадающие типы
для данного пула генов:

 match_index <- function(genes) {
  matches <- index %>% 
    group_by(type, subtype) %>% 
    filter(all(markers %in% genes)) %>% 
    distinct(type, subtype)

  # If none matched, return a row of NAs  
  if (nrow(matches)) matches else matches[NA_integer_, ]
}
  

Затем вы можете просто суммировать каждый кластер с помощью функции:

 clusters %>% 
  group_by(cluster) %>% 
  summarise(match_index(genes))
#> `summarise()` regrouping output by 'cluster' (override with `.groups` argument)
#> # A tibble: 4 x 3
#> # Groups:   cluster [3]
#>   cluster type  subtype
#>     <dbl> <chr> <chr>  
#> 1       0 AB    X      
#> 2       0 BC    Y      
#> 3       1 BC    Y      
#> 4       2 <NA>  <NA>