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)