Изменить матрицу данных в матрице с 0 и 1 информацией с R - PullRequest
0 голосов
/ 05 февраля 2019

У меня есть фрейм данных, такой как:

Cluster sequence_name
1       species1
1       species1
1       species2
1       species3
1       species3
1       gene1
1       gene2
2       species4
2       species5
2       spciess5
2       species3
2       gene3
2       gene4

, и я хотел бы получить с ним матрицу, такую ​​как:

           gene1  gene2 gene3 gene4
species5   0      0     1     1
species4   0      0     1     1
species1   1      1     0     0
species2   1      1     0     0
species3   1      1     1     1

, где 1 означает, что для speciesX ген присутствует, а 0 означает, что его нет.Присутствие означает, что speciesX присутствует в same cluster, чем geneX.Например, gene1 присутствует в cluster1 как species1, 2 and 3.Напротив, species5 and 4 не присутствуют в cluster1.

Как вы также можете видеть;Есть несколько дубликатов (в одном кластере вид может быть представлен несколько раз).Спасибо за вашу помощь.

Реальные данные выглядят так:

cluster_names seq_names  
1             AP_000401.1  
1             NP_039001.1  
1             Canis_lupus  
1             Canis_familiaris
2             YP_0090909.1
2             Mustela_putorius
2             Mustela_furo
2             YP_0909200.1

....

...

AP и NP, а другие буквы XX являются генами иGenus_specie the разновидность

В ответ на Дениса:

Вот заголовок реальных данных:

cluster_names  seq_names
1   scf7180005155889:2745-3053(-):Drosophia_melanogaster
1   IDBA_scaffold_72878:85-225:292707-293006(+):Orussu_sp
1   scaffold_3615:40850-41320(-):Canis_lupus
1   scaffold_8697:754-1209(-):homo_sapiens
1   scf7180005155889:72-1908(-):homo_sapiens
1   YP_003969716.1
1   NP_003986717.1
2   scaffold_17536:2745-3053(-):Drosophia_melanogaster
2   scf7180005155889:2000-8900(-):Drosophia_melanogaster
2   scaffold_8697:754-1209(-):homo_sapiens
2   YP_003956764.1
2   YP_004894416.1
2   YP_008958968.1

и вывод, который я должен получить:

output

В ответ на Дениса:

> df <- read.table(text = "Cluster sequence_name
+ 1       :Drosophia_melanogaster
+                  1       scf7180005155889:2745-3053(-):Drosophila_melanogaster
+                  1       scf7180005155889:2745-3053(-):Orussu_sp
+                  1       scf7180005155889:2745-3053(-):Canis_lupus
+                  1       scf7180005155889:72-1908(-):Homo_sapiens
+                  1       scf7180005155889:2745-3053(-):Homo_sapiens
+                  1       YP_003970075.1
+                  1       YP_005070075.1
+                  2       scf7180005155889:72-1908(-):Drosophila_melanogaster
+                  2       scf7180005155889:72-1908(-):Drosophila_melanogaster
+                  2       scf7180005155889:72-1908(-):Homo_sapiens
+                  2       YP_039970075.1
+                  2       NP_003900075.1",header = T)
> df <- setDT(df)
> species <- df[grep("[0-9]+\\([+-]\\):[A-z ]+",sequence_name)]
> species[,sequence_name := str_extract(sequence_name,"(?<=[0-9]\\([+-]\\):)[A-z ]+")]
> genes <- df[grep("[0-9]+\\.1",sequence_name)]
> genes[,sequence_name :=sequence_name]
> plouf <- merge(genes,species,by = "Cluster",allow.cartesian=TRUE)
> result <- dcast(plouf,sequence_name.y~sequence_name.x,fun.aggregate = length)
Using 'sequence_name.y' as value column. Use 'value.var' to override
> row.names(result)<-result$sequence_name.y
> result$sequence_name.y<- NULL
> result
   NP_003900075.1 YP_003970075.1 YP_005070075.1 YP_039970075.1
1:              0              1              1              0
2:              2              1              1              2
3:              1              2              2              1
4:              0              1              1              0

Ответы [ 2 ]

0 голосов
/ 05 февраля 2019

Использование tidyverse :

# data
df1 <- read.table(text = "Cluster sequence_name
1       species1
                  1       species1
                  1       species2
                  1       species3
                  1       species3
                  1       gene1
                  1       gene2
                  2       species4
                  2       species5
                  2       species5
                  2       species3
                  2       gene3
                  2       gene4", header = TRUE, stringsAsFactors = FALSE)

# so that we know which row is species
species <- paste("species", 1:5, sep = "")
#[1] "species1" "species2" "species3" "species4" "species5"

library(tidyverse)

res <- reduce(split(df1, df1$sequence_name %in% species), left_join, by = "Cluster") %>% 
  unique() %>% 
  spread(key = "sequence_name.x", value = "Cluster") %>% 
  mutate_if(is.numeric,  funs(as.numeric(!is.na(.))))

res
#   sequence_name.y gene1 gene2 gene3 gene4
# 1        species1     1     1     0     0
# 2        species2     1     1     0     0
# 3        species3     1     1     1     1
# 4        species4     0     0     1     1
# 5        species5     0     0     1     1
0 голосов
/ 05 февраля 2019
library(data.table)
library(stringr)
df <- setDT(df)

Я буду использовать data.table здесь.Таким образом, идея состоит в том, чтобы создать два фрейма данных, один с генами, один с видами

species <- df[grep("species",sequence_name)]
species[,sequence_name := str_extract(sequence_name,"(?<=:)[a-z0-9]+$")]
genes <- df[grep("gene",sequence_name)]

> species
   Cluster sequence_name
1:       1      species1
2:       1      species2
3:       1      species3
4:       2      species4
5:       2      species5
6:       2      species3
> genes
   Cluster sequence_name
1:       1         gene1
2:       1         gene2
3:       2         gene3
4:       2         gene4

Вы хотите объединить их вместе по кластеру с allow.cartesian=TRUE, потому что ваш вектор слияния не является единым идентификаторомни для одного из ваших data.frame:

plouf <- merge(genes,species,by = "Cluster",allow.cartesian=TRUE)

    Cluster sequence_name.x sequence_name.y
 1:       1           gene1        species1
 2:       1           gene1        species2
 3:       1           gene1        species3
 4:       1           gene2        species1
 5:       1           gene2        species2
 6:       1           gene2        species3
 7:       2           gene3        species4
 8:       2           gene3        species5
 9:       2           gene3        species3
10:       2           gene4        species4
11:       2           gene4        species5
12:       2           gene4        species3

Затем, получение вашего результата просто идет в широкоформатный формат при подсчете количества вхождений, что вы можете сделать с помощью dcast здесь:

result <- dcast(plouf,sequence_name.y~sequence_name.x,fun.aggregate = length)


   sequence_name.y gene1 gene2 gene3 gene4
1:        species1     1     1     0     0
2:        species2     1     1     0     0
3:        species3     1     1     1     1
4:        species4     0     0     1     1
5:        species5     0     0     1     1

Et voilà.Я позволил dplyr опытным пользователям предложить эквивалентное / улучшенное решение с dplyr.

Данные:

df <- read.table(text = "Cluster sequence_name
1       Scaffold_1:species1
                 1       Scaffold_2:species2
                 1       Scaffold_3:species3
                 1       gene1
                 1       gene2
                 2       Scaffold_4:species4
                 2       Scaffold_5:species5
                 2       Scaffold_6:species3
                 2       gene3
                 2       gene4",header = T)

С реальными данными, которые вы показываете:

df <- read.table(text ="cluster_names  seq_names
                 1   scf7180005155889:2745-3053(-):Drosophia_melanogaster
                 1   scaffold_2484:292707-293006(+):Orussu_sp
                 1   scaffold_3615:40850-41320(-):Canis_lupus
                 1   scaffold_8697:754-1209(-):homo_sapiens
                 1   scf7180005155889:72-1908(-):homo_sapiens
                 1   YP_003969716.1
                 1   NP_003986717.1
                 2   scaffold_17536:2745-3053(-):Drosophia_melanogaster
                 2   scf7180005155889:2000-8900(-):Drosophia_melanogaster
                 2   scaffold_8697:754-1209(-):homo_sapiens
                 2   YP_003956764.1
                 2   YP_004894416.1
                 2   YP_008958968.1",header = T)

Вам следует изменить шаг создания таблицы данных следующим образом:

species <- df[grep("[0-9]+\\([+-]\\):[A-z ]+",seq_names)]
species[,sequence_name := str_extract(seq_names,"(?<=[0-9]\\([+-]\\):)[A-z ]+")]
genes <- df[grep("[0-9]+\\.1",seq_names)]
genes[,sequence_name :=seq_names]

Здесь "[0-9]+\\.1" предположим, что все гены заканчиваются 1, и что в описании вида нет смысла,Для извлечения информации о видах, я предполагаю, что она всегда содержит (+): или (-)+ после чисел.

Но это проблема регулярных выражений, и это должно быть вопросом другого вопроса, если у вас есть проблемы с ним.Ваш вопрос здесь заключался в том, чтобы найти способ формирования данных для получения вашего результата.Я ответил, предоставив вам шаги, работающие с данными примера: создание фрейма данных двух генов и видов с использованием регулярных выражений, объединение их и изменение их формы.

Остальное работает:

plouf <- merge(genes,species,by = "cluster_names",allow.cartesian=TRUE)
result <- dcast(plouf,sequence_name.y~sequence_name.x,fun.aggregate = length)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...