SciPy Yığını ile Genomunuza Kapsamlı Bir Giriş
Yayınlanan: 2022-03-11Biyoinformatik, biyolojik verileri analiz etmek ve anlamak için yöntemler ve yazılım araçları geliştiren disiplinler arası bir alandır.
Daha basit bir ifadeyle, bunu biyoloji için veri bilimi olarak düşünebilirsiniz.
Birçok biyolojik veri türü arasında genomik veriler en yaygın olarak analiz edilenlerden biridir. Özellikle yeni nesil DNA dizileme (NGS) teknolojilerinin hızlı ilerlemesiyle, genomik verilerin hacmi katlanarak büyüyor. Stephens, Zachary D ve arkadaşlarına göre, genomik veri toplama yıllık eksabayt ölçeğindedir.
Bu yazıda, insan genomu için bir GFF3 dosyasını SciPy Yığını ile analiz etmenin bir örneğini gösteriyorum. Genel Özellik Biçimi Sürüm 3 (GFF3), genomik özellikleri depolamak için geçerli standart metin dosyası biçimidir. Özellikle bu gönderide, insan genomuyla ilgili aşağıdaki soruları yanıtlamak için SciPy yığınını nasıl kullanacağınızı öğreneceksiniz:
- Genomun ne kadarı eksik?
- Genomda kaç gen var?
- Tipik bir gen ne kadardır?
- Kromozomlar arasındaki gen dağılımı nasıldır?
İnsan genomu için en son GFF3 dosyası buradan indirilebilir. Bu dizinde gelen BENİOKU dosyası bu veri biçiminin kısa bir açıklamasını sağlar ve burada daha ayrıntılı bir belirtim bulunur.
GFF3 dosyasını manipüle etmek ve anlamak için hızlı, esnek ve anlamlı veri yapıları sağlayan SciPy yığınının önemli bir bileşeni olan Panda'ları kullanacağız.
Kurmak
İlk önce, SciPy yığınının kurulu olduğu bir sanal ortam kuralım. Yığın, bazıları harici FORTRAN veya C koduna bağlı olan birçok paketi içerdiğinden, kaynaktan manuel olarak oluşturulursa bu işlem zaman alıcı olabilir. Burada kurulumu çok kolaylaştıran Miniconda'yı kullanmanızı öneririm.
wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh bash Miniconda3-latest-Linux-x86_64.sh -b
Bash satırındaki -b
bayrağı, toplu iş modunda yürütülmesini söyler. Miniconda'yı başarılı bir şekilde kurmak için yukarıdaki komutlar kullanıldıktan sonra, genomik için yeni bir sanal ortam başlatın ve ardından SciPy yığınını kurun.
mkdir -p genomics cd genomics conda create -p venv ipython matplotlib pandas
Bu yazıda kullanacağımız sadece 3 paketi belirttiğimizi unutmayın. SciPy yığınında listelenen tüm paketleri istiyorsanız, bunları conda create
komutunun sonuna eklemeniz yeterlidir.
Bir paketin tam adından emin değilseniz, conda search
deneyin. Sanal ortamı etkinleştirelim ve IPython'u başlatalım.
source activate venv/ ipython
IPython, varsayılan Python yorumlayıcı arabiriminin önemli ölçüde daha güçlü bir alternatifidir, bu nedenle varsayılan python yorumlayıcısında yaptığınız her şey IPython'da da yapılabilir. Henüz IPython kullanmayan her Python programcısının denemesini şiddetle tavsiye ederim.
Açıklama Dosyasını İndirin
Kurulumumuz tamamlandığına göre insan genomu açıklama dosyasını GFF3 formatında indirelim.
Düz metin olarak yaklaşık 3 GB olan bir insan genomunun bilgi içeriğine kıyasla çok küçük bir dosya olan yaklaşık 37 MB'dir. Bunun nedeni, GFF3 dosyasının yalnızca dizilerin açıklamalarını içermesi ve dizi verilerinin genellikle FASTA adı verilen başka bir dosya biçiminde saklanmasıdır. İlgileniyorsanız, FASTA'yı buradan indirebilirsiniz, ancak bu eğitimde dizi verilerini kullanmayacağız.
!wget ftp://ftp.ensembl.org/pub/release-85/gff3/homo_sapiens/Homo_sapiens.GRCh38.85.gff3.gz
Ön ek !
IPython'a bunun bir Python komutu yerine bir kabuk komutu olduğunu söyler. Ancak, IPython ayrıca ls
, pwd
, rm
, mkdir
, rmdir
gibi sık kullanılan bazı kabuk komutlarını önek olmadan da işleyebilir !
.
GFF dosyasının başına bir göz attığınızda, ##
veya #!
.
README'ye göre, ##
meta verinin kararlı olduğu anlamına gelirken, #!
deneysel olduğu anlamına gelir.
Daha sonra, spesifikasyona dayalı olarak daha ince anlamlara sahip başka bir yönerge olan ###
'yi de göreceksiniz.
İnsan tarafından okunabilen yorumların tek bir #
işaretinden sonra olması gerekir. Basit olması için, #
ile başlayan tüm satırları yorum olarak ele alacağız ve analizimiz sırasında bunları görmezden geleceğiz.
##gff-version 3 ##sequence-region 1 1 248956422 ##sequence-region 10 1 133797422 ##sequence-region 11 1 135086622 ##sequence-region 12 1 133275309 ... ##sequence-region MT 1 16569 ##sequence-region X 1 156040895 ##sequence-region Y 2781480 56887902 #!genome-build GRCh38.p7 #!genome-version GRCh38 #!genome-date 2013-12 #!genome-build-accession NCBI:GCA_000001405.22 #!genebuild-last-updated 2016-06
İlk satır, bu dosyada kullanılan GFF formatının sürümünün 3 olduğunu gösterir.
Bunu, tüm dizi bölgelerinin özetleri takip eder. Daha sonra göreceğimiz gibi, bu tür bilgiler dosyanın gövde kısmında da bulunabilir.
#!
bu açıklama dosyasının geçerli olduğu GRCh38.p7 genomunun belirli yapısı hakkında bilgileri gösterir.
Genom Referans Konsorsiyumu (GCR), insan, fare, zebra balığı ve tavuk için olanlar da dahil olmak üzere çeşitli referans genom düzeneklerindeki güncellemeleri ve iyileştirmeleri denetleyen uluslararası bir konsorsiyumdur.
Bu dosyayı tararken, işte ilk birkaç açıklama satırı.
1 GRCh38 chromosome 1 248956422 . . . ID=chromosome:1;Alias=CM000663.2,chr1,NC_000001.11 ### 1 . biological_region 10469 11240 1.3e+03 . . external_name=oe %3D 0.79;logic_name=cpg 1 . biological_region 10650 10657 0.999 + . logic_name=eponine 1 . biological_region 10655 10657 0.999 - . logic_name=eponine 1 . biological_region 10678 10687 0.999 + . logic_name=eponine 1 . biological_region 10681 10688 0.999 - . logic_name=eponine ...
Sütunlar seqid , source , type , start , end , skor , iplik , faz , niteliklerdir . Bazılarını anlamak çok kolaydır. İlk satırı örnek olarak alın:
1 GRCh38 chromosome 1 248956422 . . . ID=chromosome:1;Alias=CM000663.2,chr1,NC_000001.11
Bu, birinci bazdan 24.895.622. baza başlayan 1 sıralı birinci kromozomun açıklamasıdır.
Başka bir deyişle, ilk kromozom yaklaşık 25 milyon baz uzunluğundadır.
Analizimiz, değeri olan üç sütundan gelen bilgilere ihtiyaç duymayacaktır .
(yani puan, şerit ve aşama), bu yüzden şimdilik onları görmezden gelebiliriz.
Son nitelikler sütununda Chromosome 1'in ayrıca CM000663.2, chr1 ve NC_000001.11 olmak üzere üç takma adı olduğu yazıyor. Temelde bir GFF3 dosyası böyle görünür, ancak onları satır satır incelemeyeceğiz, bu yüzden tüm dosyayı Pandalara yükleme zamanı.
Pandalar, sekmeyle ayrılmış bir dosya olduğu için GFF3 biçimiyle uğraşmak için uygundur ve Pandalar, CSV benzeri dosyaları okumak için çok iyi bir desteğe sahiptir.
Sekmeyle ayrılmış biçimin bir istisnasının, GFF3'ün ##FASTA
içermesi olduğuna dikkat edin.
Spesifikasyona göre, ##FASTA
, FASTA (sekmeyle sınırlandırılmamış) formatında bir veya daha fazla diziyle takip edilecek olan bir açıklama bölümünün sonunu belirtir. Ancak analiz edeceğimiz GFF3 dosyası için durum böyle değil.
In [1]: import pandas as pd In [2]: pd.__version__ Out[2]: '0.18.1' In [3]: col_names = ['seqid', 'source', 'type', 'start', 'end', 'score', 'strand', 'phase', 'attributes'] Out[3]: df = pd.read_csv('Homo_sapiens.GRCh38.85.gff3.gz', compression='gzip', sep='\t', comment='#', low_memory=False, header=None, names=col_names)
Yukarıdaki son satır, tüm GFF3 dosyasını pandas.read_csv
yöntemiyle yükler.
Standart bir CSV dosyası olmadığı için aramayı biraz özelleştirmemiz gerekiyor.
İlk olarak, GFF3'te başlık bilgisinin kullanılamadığı konusunda Pandaları header=None
ile bilgilendiririz ve ardından her sütun için names=col_names
ile tam adı belirtiriz.
names
bağımsız değişkeni belirtilmezse, Pandalar her sütun için ad olarak artan sayıları kullanır.
sep='\t'
Pandalara sütunların virgülle ayrılmak yerine sekmeyle ayrıldığını söyler. sep=
'nin değeri aslında bir normal ifade (regex) olabilir. Eldeki dosya her sütun için farklı ayırıcılar kullanıyorsa bu kullanışlı olur (oh evet, bu olur). comment='#'
, #
ile başlayan satırların yorum olarak kabul edildiği ve yok sayılacağı anlamına gelir.
compression='gzip'
Panda'lara girdi dosyasının bir gzip sıkıştırılmış olduğunu söyler.
Ayrıca pandas.read_csv
, farklı CSV benzeri dosya biçimlerinin okunmasına izin veren zengin bir parametre grubuna sahiptir.
Döndürülen değerin türü, Pandalarda 2B verileri temsil etmek için kullanılan en önemli veri yapısı olan DataFrame
.
Pandalar ayrıca sırasıyla 1B ve 3B veriler için bir Series
ve Panel
veri yapısına sahiptir. Pandaların veri yapılarına giriş için lütfen belgelere bakın.
.head
yöntemi ile ilk birkaç girdiye bir göz atalım.
In [18]: df.head() Out[18]: seqid source type start end score strand phase attributes 0 1 GRCh38 chromosome 1 248956422 . . . ID=chromosome:1;Alias=CM000663.2,chr1,NC_00000... 1 1 . biological_region 10469 11240 1.3e+03 . . external_name=oe %3D 0.79;logic_name=cpg 2 1 . biological_region 10650 10657 0.999 + . logic_name=eponine 3 1 . biological_region 10655 10657 0.999 - . logic_name=eponine 4 1 . biological_region 10678 10687 0.999 + . logic_name=eponine
Çıktı, nitelikler sütununda kısmen ...
ile değiştirilen daha uzun dizelerle tablo biçiminde güzel bir şekilde biçimlendirilmiştir.
Pandaları, pd.set_option('display.max_colwidth', -1)
ile uzun dizeleri atlamayacak şekilde ayarlayabilirsiniz. Ayrıca Pandaların özelleştirilebilen birçok seçeneği vardır.
Ardından, .info
yöntemiyle bu veri çerçevesi hakkında bazı temel bilgileri alalım.
In [20]: df.info() <class 'pandas.core.frame.DataFrame'> RangeIndex: 2601849 entries, 0 to 2601848 Data columns (total 9 columns): seqid object source object type object start int64 end int64 score object strand object phase object attributes object dtypes: int64(2), object(7) memory usage: 178.7+ MB
Bu, GFF3'ün 2.601.848 açıklamalı satıra sahip olduğunu ve her satırın dokuz sütuna sahip olduğunu gösterir.
Her sütun için veri türlerini de gösterir.
Bu başlangıç ve bitiş, genomdaki konumları temsil eden tam sayılar olan int64 tipindedir.
Diğer sütunların tümü object
; bu, muhtemelen değerlerinin bir tamsayı, kayan nokta ve dize karışımından oluştuğu anlamına gelir.
Tüm bilgilerin boyutu, bellekte depolanan yaklaşık 178.7+ MB'dir. Bu, yaklaşık 402 MB olacak sıkıştırılmamış dosyadan daha kompakt olduğu ortaya çıkıyor. Aşağıda hızlı bir doğrulama gösterilmektedir.
gunzip -c Homo_sapiens.GRCh38.85.gff3.gz > /tmp/tmp.gff3 && du -s /tmp/tmp.gff3 402M /tmp/tmp.gff3
Üst düzey bir görünümden, GFF3 dosyasının tamamını Python'da bir DataFrame nesnesine yükledik ve aşağıdaki analizlerimizin tümü bu tek nesneye dayalı olacaktır.
Şimdi, birinci sütun seqid'in ne hakkında olduğunu görelim.
In [29]: df.seqid.unique() Out[29]: array(['1', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '2', '20', '21', '22', '3', '4', '5', '6', '7', '8', '9', 'GL000008.2', 'GL000009.2', 'GL000194.1', 'GL000195.1', ... 'KI270757.1', 'MT', 'X', 'Y'], dtype=object) In [30]: df.seqid.unique().shape Out[30]: (194,)
df.seqid
, bir veri çerçevesinden sütun verilerine erişmenin bir yoludur. Başka bir yol, daha genel bir sözdizimi olan df['seqid']
, çünkü sütun adı Python'a ayrılmış bir anahtar kelimeyse (örn. class
) veya bir .
veya boşluk karakteri, ilk yol ( df.seqid
) çalışmayacaktır.
Çıktı, 1 ila 22 Kromozomları, X, Y ve mitokondri (MT) DNA'sının yanı sıra 169 diğer diziyi içeren 194 benzersiz dizi olduğunu göstermektedir.
KI ve GL ile başlayan diziler, genomdaki kromozomlara başarılı bir şekilde monte edilmemiş DNA dizileridir - veya yapı iskeleleridir -.
Genomik ile aşina olmayanlar için bu önemlidir.
İlk insan genomu taslağı 15 yıldan fazla bir süre önce ortaya çıkmış olsa da, mevcut insan genomu hala eksik. Bu dizilerin bir araya getirilmesindeki zorluk, büyük ölçüde genomdaki karmaşık tekrarlayan bölgelerden kaynaklanmaktadır.
Ardından, kaynak sütuna bir göz atalım.
README, kaynağın, bu özelliği oluşturan algoritmayı veya işletim prosedürünü tanımlamayı amaçlayan bir serbest metin niteleyicisi olduğunu söylüyor.
In [66]: df.source.value_counts() Out[66]: havana 1441093 ensembl_havana 745065 ensembl 228212 . 182510 mirbase 4701 GRCh38 194 insdc 74
Bu, kategorik değişkenlerin hızlı sayımı için son derece yararlı olan value_counts
yönteminin kullanımına bir örnektir.
Sonuç olarak, bu sütun için yedi olası değer olduğunu ve GFF3 dosyasındaki girişlerin çoğunun havana, ensembl ve ensembl_havana'dan geldiğini görebiliriz.
Bu kaynakların ne anlama geldiği ve aralarındaki ilişkiler hakkında bu yazıda daha fazla bilgi edinebilirsiniz.
İşleri basit tutmak için GRCh38, havana, ensembl ve ensembl_havan.a kaynaklarından girişlere odaklanacağız.
Genomun Ne Kadarı Eksik?
Her bir kromozom hakkındaki bilgiler GRCh38 kaynağındaki girişlerdedir, bu yüzden önce gerisini filtreleyelim ve filtrelenmiş sonucu yeni bir değişkene atayalım gdf
.
In [70]: gdf = df[df.source == 'GRCh38'] In [87]: gdf.shape Out[87]: (194, 9) In [84]: gdf.sample(10) Out[84]: seqid source type start end score strand phase attributes 2511585 KI270708.1 GRCh38 supercontig 1 127682 . . . ID=supercontig:KI270708.1;Alias=chr1_KI270708v... 2510840 GL000208.1 GRCh38 supercontig 1 92689 . . . ID=supercontig:GL000208.1;Alias=chr5_GL000208v... 990810 17 GRCh38 chromosome 1 83257441 . . . ID=chromosome:17;Alias=CM000679.2,chr17,NC_000... 2511481 KI270373.1 GRCh38 supercontig 1 1451 . . . ID=supercontig:KI270373.1;Alias=chrUn_KI270373... 2511490 KI270384.1 GRCh38 supercontig 1 1658 . . . ID=supercontig:KI270384.1;Alias=chrUn_KI270384... 2080148 6 GRCh38 chromosome 1 170805979 . . . ID=chromosome:6;Alias=CM000668.2,chr6,NC_00000... 2511504 KI270412.1 GRCh38 supercontig 1 1179 . . . ID=supercontig:KI270412.1;Alias=chrUn_KI270412... 1201561 19 GRCh38 chromosome 1 58617616 . . . ID=chromosome:19;Alias=CM000681.2,chr19,NC_000... 2511474 KI270340.1 GRCh38 supercontig 1 1428 . . . ID=supercontig:KI270340.1;Alias=chrUn_KI270340... 2594560 Y GRCh38 chromosome 2781480 56887902 . . . ID=chromosome:Y;Alias=CM000686.2,chrY,NC_00002...
Pandalarda filtreleme yapmak kolaydır.
df.source == 'GRCh38'
ifadesinden değerlendirilen değeri incelerseniz, bu, df
ile aynı dizine sahip her giriş için bir dizi True
ve False
değeridir. Bunu df[]
, yalnızca karşılık gelen değerlerinin True olduğu girişleri döndürür.
df[]
içinde df.source == 'GRCh38'
olan 194 anahtar vardır.
Daha önce gördüğümüz gibi, seqid
sütununda ayrıca 194 benzersiz değer vardır, yani gdf'deki her giriş belirli bir gdf
karşılık gelir.
Daha sonra daha yakından bakmak için sample
yöntemiyle rastgele 10 giriş seçiyoruz.
Birleştirilmemiş dizilerin supercontig tipinde olduğunu, diğerlerinin ise kromozom olduğunu görebilirsiniz. Eksik genom fraksiyonunu hesaplamak için, önce tüm genomun uzunluğunu bilmemiz gerekir, bu da tüm dizilerin uzunluklarının toplamıdır.
In [90]: gdf = gdf.copy() In [91]: gdf['length'] = gdf.end - gdf.start + 1 In [93]: gdf.head() Out[93]: seqid source type start end score strand phase attributes length 0 1 GRCh38 chromosome 1 248956422 . . . ID=chromosome:1;Alias=CM000663.2,chr1,NC_00000... 248956421 235068 10 GRCh38 chromosome 1 133797422 . . . ID=chromosome:10;Alias=CM000672.2,chr10,NC_000... 133797421 328938 11 GRCh38 chromosome 1 135086622 . . . ID=chromosome:11;Alias=CM000673.2,chr11,NC_000... 135086621 483370 12 GRCh38 chromosome 1 133275309 . . . ID=chromosome:12;Alias=CM000674.2,chr12,NC_000... 133275308 634486 13 GRCh38 chromosome 1 114364328 . . . ID=chromosome:13;Alias=CM000675.2,chr13,NC_000... 114364327 In [97]: gdf.length.sum() Out[97]: 3096629532 In [99]: chrs = [str(_) for _ in range(1, 23)] + ['X', 'Y', 'MT'] In [101]: gdf[-gdf.seqid.isin(chrs)].length.sum() / gdf.length.sum() Out[101]: 0.0037021917421198327
Yukarıdaki pasajda önce, .copy()
ile gdf
bir kopyasını yaptık. Aksi takdirde, orijinal gdf
yalnızca bir df
dilimidir ve onu doğrudan değiştirmek SettingWithCopyWarning
ile sonuçlanır (daha fazla ayrıntı için buraya bakın).
Daha sonra her bir girdinin uzunluğunu hesaplıyoruz ve onu "uzunluk" adlı yeni bir sütun olarak gdf
geri ekliyoruz. Toplam uzunluk yaklaşık 3,1 milyar ve birleştirilmemiş dizilerin oranı yaklaşık %0,37'dir.
Son iki komutta dilimleme şu şekilde çalışır.
İlk olarak, tümü kromozom ve mitokondri olan iyi birleştirilmiş dizilerin tüm dizilerini kapsayan bir dizi listesi oluşturuyoruz. Daha sonra chrs
listesindeki tüm girdileri filtrelemek için isin
yöntemini kullanırız.
Seçimi tersine çevirmek için indeksin başına bir eksi işareti ( -
) eklenir, çünkü aslında listede olmayan her şeyi istiyoruz (yani KI ve GL ile başlayan demonte olanları istiyoruz)…
Not: Birleştirilmiş ve birleştirilmemiş diziler, tip sütunuyla ayırt edildiğinden, aynı sonuçları elde etmek için son satır alternatif olarak aşağıdaki gibi yeniden yazılabilir.
gdf[(gdf['type'] == 'supercontig')].length.sum() / gdf.length.sum()
Kaç Gen Var?
Burada, ek açıklama girişlerinin çoğunluğunun ait olduğu kaynak ensembl, havana ve ensembl_havana'daki girişlere odaklanıyoruz.
In [109]: edf = df[df.source.isin(['ensembl', 'havana', 'ensembl_havana'])] In [111]: edf.sample(10) Out[111]: seqid source type start end score strand phase attributes 915996 16 havana CDS 27463541 27463592 . - 2 ID=CDS:ENSP00000457449;Parent=transcript:ENST0... 2531429 X havana exon 41196251 41196359 . + . Parent=transcript:ENST00000462850;Name=ENSE000... 1221944 19 ensembl_havana CDS 5641740 5641946 . + 0 ID=CDS:ENSP00000467423;Parent=transcript:ENST0... 243070 10 havana exon 13116267 13116340 . + . Parent=transcript:ENST00000378764;Name=ENSE000... 2413583 8 ensembl_havana exon 144359184 144359423 . + . Parent=transcript:ENST00000530047;Name=ENSE000... 2160496 6 havana exon 111322569 111322678 . - . Parent=transcript:ENST00000434009;Name=ENSE000... 839952 15 havana exon 76227713 76227897 . - . Parent=transcript:ENST00000565910;Name=ENSE000... 957782 16 ensembl_havana exon 67541653 67541782 . + . Parent=transcript:ENST00000379312;Name=ENSE000... 1632979 21 ensembl_havana exon 37840658 37840709 . - . Parent=transcript:ENST00000609713;Name=ENSE000... 1953399 4 havana exon 165464390 165464586 . + . Parent=transcript:ENST00000511992;Name=ENSE000... In [123]: edf.type.value_counts() Out[123]: exon 1180596 CDS 704604 five_prime_UTR 142387 three_prime_UTR 133938 transcript 96375 gene 42470 processed_transcript 28228 ... Name: type, dtype: int64
Filtreleme için yine isin
yöntemi kullanılır.
Ardından, hızlı bir değer sayımı, girişlerin çoğunun ekson, kodlama dizisi (CDS) ve çevrilmemiş bölge (UTR) olduğunu gösterir.
Bunlar alt gen unsurlarıdır, ancak biz esas olarak gen sayısını arıyoruz. Gösterildiği gibi, 42.470 var, ancak daha fazlasını bilmek istiyoruz.
Özellikle, isimleri nelerdir ve ne yaparlar? Bu soruları cevaplamak için, nitelikler sütunundaki bilgilere yakından bakmamız gerekiyor.
In [127]: ndf = edf[edf.type == 'gene'] In [173]: ndf = ndf.copy() In [133]: ndf.sample(10).attributes.values Out[133]: array(['ID=gene:ENSG00000228611;Name=HNF4GP1;biotype=processed_pseudogene;description=hepatocyte nuclear factor 4 gamma pseudogene 1 [Source:HGNC Symbol%3BAcc:HGNC:35417];gene_id=ENSG00000228611;havana_gene=OTTHUMG00000016986;havana_version=2;logic_name=havana;version=2', 'ID=gene:ENSG00000177189;Name=RPS6KA3;biotype=protein_coding;description=ribosomal protein S6 kinase A3 [Source:HGNC Symbol%3BAcc:HGNC:10432];gene_id=ENSG00000177189;havana_gene=OTTHUMG00000021231;havana_version=5;logic_name=ensembl_havana_gene;version=12', 'ID=gene:ENSG00000231748;Name=RP11-227H15.5;biotype=antisense;gene_id=ENSG00000231748;havana_gene=OTTHUMG00000018373;havana_version=1;logic_name=havana;version=1', 'ID=gene:ENSG00000227426;Name=VN1R33P;biotype=unitary_pseudogene;description=vomeronasal 1 receptor 33 pseudogene [Source:HGNC Symbol%3BAcc:HGNC:37353];gene_id=ENSG00000227426;havana_gene=OTTHUMG00000154474;havana_version=1;logic_name=havana;version=1', 'ID=gene:ENSG00000087250;Name=MT3;biotype=protein_coding;description=metallothionein 3 [Source:HGNC Symbol%3BAcc:HGNC:7408];gene_id=ENSG00000087250;havana_gene=OTTHUMG00000133282;havana_version=3;logic_name=ensembl_havana_gene;version=8', 'ID=gene:ENSG00000177108;Name=ZDHHC22;biotype=protein_coding;description=zinc finger DHHC-type containing 22 [Source:HGNC Symbol%3BAcc:HGNC:20106];gene_id=ENSG00000177108;havana_gene=OTTHUMG00000171575;havana_version=3;logic_name=ensembl_havana_gene;version=5', 'ID=gene:ENSG00000249784;Name=SCARNA22;biotype=scaRNA;description=small Cajal body-specific RNA 22 [Source:HGNC Symbol%3BAcc:HGNC:32580];gene_id=ENSG00000249784;logic_name=ncrna;version=1', 'ID=gene:ENSG00000079101;Name=CLUL1;biotype=protein_coding;description=clusterin like 1 [Source:HGNC Symbol%3BAcc:HGNC:2096];gene_id=ENSG00000079101;havana_gene=OTTHUMG00000178252;havana_version=7;logic_name=ensembl_havana_gene;version=16', 'ID=gene:ENSG00000229224;Name=AC105398.3;biotype=antisense;gene_id=ENSG00000229224;havana_gene=OTTHUMG00000152025;havana_version=1;logic_name=havana;version=1', 'ID=gene:ENSG00000255552;Name=LY6G6E;biotype=protein_coding;description=lymphocyte antigen 6 complex%2C locus G6E (pseudogene) [Source:HGNC Symbol%3BAcc:HGNC:13934];gene_id=ENSG00000255552;havana_gene=OTTHUMG00000166419;havana_version=1;logic_name=ensembl_havana_gene;version=7'], dtype=object)
Etiket-değer çiftlerinin noktalı virgülle ayrılmış listesi olarak biçimlendirilirler. En çok ilgilendiğimiz bilgiler gen adı, gen kimliği ve tanımıdır ve bunları düzenli ifade (regex) ile çıkaracağız.

import re RE_GENE_NAME = re.compile(r'Name=(?P<gene_name>.+?);') def extract_gene_name(attributes_str): res = RE_GENE_NAME.search(attributes_str) return res.group('gene_name') ndf['gene_name'] = ndf.attributes.apply(extract_gene_name)
İlk önce gen isimlerini çıkarıyoruz.
Normal Name=(?P<gene_name>.+?);
, +?
+
yerine kullanılır, çünkü onun açgözlü olmamasını ve aramanın ilk noktalı virgülde durmasını istiyoruz; aksi takdirde sonuç son noktalı virgülle eşleşir.
Ayrıca, normal ifade, daha iyi performans için araştırmadaki gibi doğrudan kullanılmak yerine, ilk önce yeniden derleme ile re.compile
, çünkü onu binlerce öznitelik re.search
uygulayacağız.
extract_gene_name
, bir veri çerçevesinin veya serinin her girişinde bir işlevin uygulanması gerektiğinde kullanılacak yöntem olan pd.apply
kullanılacak bir yardımcı işlev olarak hizmet eder.
Bu özel durumda, ndf.attributes
içindeki her giriş için gen adını çıkarmak ve adları ndf
adlı yeni bir sütunda gene_name
.
Gen kimlikleri ve açıklama benzer şekilde çıkarılır.
RE_GENE_ID = re.compile(r'gene_id=(?P<gene_id>ENSG.+?);') def extract_gene_id(attributes_str): res = RE_GENE_ID.search(attributes_str) return res.group('gene_id') ndf['gene_id'] = ndf.attributes.apply(extract_gene_id) RE_DESC = re.compile('description=(?P<desc>.+?);') def extract_description(attributes_str): res = RE_DESC.search(attributes_str) if res is None: return '' else: return res.group('desc') ndf['desc'] = ndf.attributes.apply(extract_description)
RE_GENE_ID
için normal ifade, her gene_id
ENSG
başlaması gerektiğini bildiğimiz için biraz daha spesifiktir; burada ENS
, topluluk anlamına gelir ve G
, gen anlamına gelir.
Herhangi bir açıklaması olmayan girişler için boş bir dize döndürürüz. Her şey ayıklandıktan sonra, artık nitelikler sütununu kullanmayacağız, bu yüzden .drop
yöntemiyle işleri güzel ve temiz tutmak için bırakalım:
In [224]: ndf.drop('attributes', axis=1, inplace=True) In [225]: ndf.head() Out[225]: seqid source type start end score strand phase gene_id gene_name desc 16 1 havana gene 11869 14409 . + . ENSG00000223972 DDX11L1 DEAD/H-box helicase 11 like 1 [Source:HGNC Sym... 28 1 havana gene 14404 29570 . - . ENSG00000227232 WASH7P WAS protein family homolog 7 pseudogene [Sourc... 71 1 havana gene 52473 53312 . + . ENSG00000268020 OR4G4P olfactory receptor family 4 subfamily G member... 74 1 havana gene 62948 63887 . + . ENSG00000240361 OR4G11P olfactory receptor family 4 subfamily G member... 77 1 ensembl_havana gene 69091 70008 . + . ENSG00000186092 OR4F5 olfactory receptor family 4 subfamily F member...
Yukarıdaki çağrıda, attributes
, bırakmak istediğimiz belirli sütunu belirtir.
axis=1
, satır yerine bir sütun bıraktığımız anlamına gelir (varsayılan olarak axis=0
).
inplace=True
, bırakma işleminin, belirtilen sütun bırakılmış yeni bir kopya döndürmek yerine DataFrame'in kendisinde çalıştırıldığı anlamına gelir.
Hızlı bir .head
görünümü, nitelikler sütununun gerçekten gittiğini ve üç yeni sütunun eklendiğini gösterir: gene_name
, gene_id
ve desc
.
Meraktan, tüm gene_id
ve gene_name
benzersiz olup olmadığını görelim:
In [232]: ndf.shape Out[232]: (42470, 11) In [233]: ndf.gene_id.unique().shape Out[233]: (42470,) In [234]: ndf.gene_name.unique().shape Out[234]: (42387,)
Şaşırtıcı bir şekilde, gen adlarının sayısı gen kimliklerinin sayısından daha küçüktür, bu da bazı gen_adlarının birden çok gen kimliğine karşılık gelmesi gerektiğini gösterir. Ne olduklarını öğrenelim.
In [243]: count_df = ndf.groupby('gene_name').count().ix[:, 0].sort_values().ix[::-1] In [244]: count_df.head(10) Out[244]: gene_name SCARNA20 7 SCARNA16 6 SCARNA17 5 SCARNA15 4 SCARNA21 4 SCARNA11 4 Clostridiales-1 3 SCARNA4 3 C1QTNF9B-AS1 2 C11orf71 2 Name: seqid, dtype: int64 In [262]: count_df[count_df > 1].shape Out[262]: (63,) In [263]: count_df.shape Out[263]: (42387,) In [264]: count_df[count_df > 1].shape[0] / count_df.shape[0] Out[264]: 0.0014863047632528842
Tüm girdileri gene_name
değerine göre gruplandırıyoruz, ardından her gruptaki öğelerin sayısını .count()
ile sayıyoruz.
ndf.groupby('gene_name').count()
çıktısını incelerseniz, her grup için tüm sütunlar sayılır, ancak çoğu aynı değerlere sahiptir.
Sayarken NA değerlerinin dikkate alınmayacağını unutmayın, bu nedenle yalnızca ilk sütun olan seqid
sayısını alın ( NA değerleri olmadığından emin olmak için .ix[:, 0]
kullanıyoruz).
Ardından sayım değerlerini .sort_values
ile sıralayın ve sırayı .ix[::-1]
ile tersine çevirin.
Sonuç olarak, bir gen adı en fazla yedi gen kimliğiyle paylaşılabilir.
In [255]: ndf[ndf.gene_name == 'SCARNA20'] Out[255]: seqid source type start end score strand phase gene_id gene_name desc 179399 1 ensembl gene 171768070 171768175 . + . ENSG00000253060 SCARNA20 Small Cajal body specific RNA 20 [Source:RFAM%3BAcc:RF00601] 201037 1 ensembl gene 204727991 204728106 . + . ENSG00000251861 SCARNA20 Small Cajal body specific RNA 20 [Source:RFAM%3BAcc:RF00601] 349203 11 ensembl gene 8555016 8555146 . + . ENSG00000252778 SCARNA20 Small Cajal body specific RNA 20 [Source:RFAM%3BAcc:RF00601] 718520 14 ensembl gene 63479272 63479413 . + . ENSG00000252800 SCARNA20 Small Cajal body specific RNA 20 [Source:RFAM%3BAcc:RF00601] 837233 15 ensembl gene 75121536 75121666 . - . ENSG00000252722 SCARNA20 Small Cajal body specific RNA 20 [Source:RFAM%3BAcc:RF00601] 1039874 17 ensembl gene 28018770 28018907 . + . ENSG00000251818 SCARNA20 Small Cajal body specific RNA 20 [Source:RFAM%3BAcc:RF00601] 1108215 17 ensembl gene 60231516 60231646 . - . ENSG00000252577 SCARNA20 small Cajal body-specific RNA 20 [Source:HGNC Symbol%3BAcc:HGNC:32578]
Tüm SCARNA20 genlerine daha yakından bakıldığında hepsinin gerçekten farklı olduğu görülüyor.
Aynı adı paylaşırken, genomun farklı konumlarında bulunurlar.
Bununla birlikte, açıklamaları onları ayırt etmede pek yardımcı görünmüyor.
Buradaki nokta, gen adlarının tüm gen kimlikleri için benzersiz olmadığını ve birden çok gen tarafından paylaşılan adların yaklaşık %0,15'inin olduğunu bilmektir.
Tipik Bir Gen Ne Kadar Uzundur?
Genomun eksikliğini anlamaya çalışırken yaptığımıza benzer şekilde, ndf
kolayca bir length
sütunu ekleyebiliriz:
In [277]: ndf['length'] = ndf.end - ndf.start + 1 In [278]: ndf.length.describe() Out[278]: count 4.247000e+04 mean 3.583348e+04 std 9.683485e+04 min 8.000000e+00 25% 8.840000e+02 50% 5.170500e+03 75% 3.055200e+04 max 2.304997e+06 Name: length, dtype: float64
.describe()
, uzunluk değerlerine dayalı olarak bazı basit istatistikleri hesaplar:
Bir genin ortalama uzunluğu yaklaşık 36.000 bazdır.
Bir genin medyan uzunluğu yaklaşık 5.200 baz uzunluğundadır.
Minimum ve maksimum gen uzunlukları sırasıyla yaklaşık sekiz ve 2.3 milyon baz uzunluğundadır.
Ortalama medyandan çok daha büyük olduğu için uzunluk dağılımının sağa çarpık olduğu anlamına gelir. Daha somut bir bakış için dağılımı çizelim.
import matplotlib as plt ndf.length.plot(kind='hist', bins=50, logy=True) plt.show()
Pandas, DataFrame'ler veya serilerle çizim yapmayı çok kullanışlı hale getirmek için matplotlib'e basit bir arayüz sağlar.
Bu durumda, 50 kutulu bir histogram grafiği ( kind='hist'
) istediğimizi ve y ekseninin bir log ölçeğinde ( logy=True
) olmasına izin verdiğimizi söylüyor.
Histogramdan, genlerin çoğunun ilk bölmede olduğunu görebiliriz. Ancak bazı gen uzunlukları iki milyon bazdan fazla olabilir. Ne olduklarını öğrenelim:
In [39]: ndf[ndf.length > 2e6].sort_values('length').ix[::-1] Out[39]: seqid source type start end score strand phase gene_name gene_id desc length 2309345 7 ensembl_havana gene 146116002 148420998 . + . CNTNAP2 ENSG00000174469 contactin associated protein-like 2 [Source:HG... 2304997 2422510 9 ensembl_havana gene 8314246 10612723 . - . PTPRD ENSG00000153707 protein tyrosine phosphatase%2C receptor type ... 2298478 2527169 X ensembl_havana gene 31097677 33339441 . - . DMD ENSG00000198947 dystrophin [Source:HGNC Symbol%3BAcc:HGNC:2928] 2241765 440886 11 ensembl_havana gene 83455012 85627922 . - . DLG2 ENSG00000150672 discs large MAGUK scaffold protein 2 [Source:H... 2172911 2323457 8 ensembl_havana gene 2935353 4994972 . - . CSMD1 ENSG00000183117 CUB and Sushi multiple domains 1 [Source:HGNC ... 2059620 1569914 20 ensembl_havana gene 13995369 16053197 . + . MACROD2 ENSG00000172264 MACRO domain containing 2 [Source:HGNC Symbol%... 2057829
Gördüğünüz gibi, en uzun gen, kontaktin ilişkili protein benzeri 2'nin kısaltması olan CNTNAP2 olarak adlandırılıyor. Onun wikipedia sayfasına göre,
Bu gen, kromozom 7'nin neredeyse %1.6'sını kapsar ve insan genomundaki en büyük genlerden biridir.
Aslında! Bunu sadece kendimiz doğruladık. Buna karşılık, en küçük genler ne olacak? Sekiz baz kadar kısa olabilecekleri ortaya çıktı.
In [40]: ndf.sort_values('length').head() Out[40]: seqid source type start end score strand phase gene_name gene_id desc length 682278 14 havana gene 22438547 22438554 . + . TRDD1 ENSG00000223997 T cell receptor delta diversity 1 [Source:HGNC... 8 682282 14 havana gene 22439007 22439015 . + . TRDD2 ENSG00000237235 T cell receptor delta diversity 2 [Source:HGNC... 9 2306836 7 havana gene 142786213 142786224 . + . TRBD1 ENSG00000282431 T cell receptor beta diversity 1 [Source:HGNC ... 12 682286 14 havana gene 22449113 22449125 . + . TRDD3 ENSG00000228985 T cell receptor delta diversity 3 [Source:HGNC... 13 1879625 4 havana gene 10238213 10238235 . - . AC006499.9 ENSG00000271544 23
İki uç durumun uzunlukları, beş büyüklük sırasıdır (2.3 milyona karşı 8), ki bu muazzamdır ve bu, yaşam çeşitliliği seviyesinin bir göstergesi olabilir.
Tek bir gen, henüz keşfetmediğimiz alternatif ekleme adı verilen bir süreçle birçok farklı proteine çevrilebilir. Bu tür bilgiler ayrıca GFF3 dosyasının içindedir, ancak bu yazının kapsamı dışındadır.
Kromozomlar Arasında Gen Dağılımı
Tartışmak istediğim son şey, iki DataFrame'i birleştirmek için .merge
yöntemini tanıtmak için bir örnek teşkil eden kromozomlar arasındaki gen dağılımıdır. Sezgisel olarak, daha uzun kromozomlar muhtemelen daha fazla gen barındırır. Bakalım bu doğru mu?
In [53]: ndf = ndf[ndf.seqid.isin(chrs)] In [54]: chr_gene_counts = ndf.groupby('seqid').count().ix[:, 0].sort_values().ix[::-1] Out[54]: chr_gene_counts seqid 1 3902 2 2806 11 2561 19 2412 17 2280 3 2204 6 2154 12 2140 7 2106 5 2002 16 1881 X 1852 4 1751 9 1659 8 1628 10 1600 15 1476 14 1449 22 996 20 965 13 872 18 766 21 541 Y 436 Name: source, dtype: int64
Önceki bölümden chrs
değişkenini ödünç aldık ve birleştirilmemiş dizileri filtrelemek için kullandık. Çıktıya göre, en büyük Kromozom 1 gerçekten de en fazla gene sahiptir. Y Kromozomu en az sayıda gene sahipken, en küçük kromozom değildir.
Mitokondride (MT) hiçbir genin bulunmadığına ve bunun doğru olmadığına dikkat edin.
pd.read_csv
tarafından döndürülen ilk DataFrame df
üzerinde biraz daha fazla filtreleme, tüm MT genlerinin kaynak insdc'den olduğunu gösterir (bunlar daha önce yalnızca havana, ensembl veya ensembl_havana kaynaklarını göz önünde bulundurduğumuz edf
oluşturulurken filtrelenmiştir).
In [134]: df[(df.type == 'gene') & (df.seqid == 'MT')] Out[134]: seqid source type start end score strand phase attributes 2514003 MT insdc gene 648 1601 . + . ID=gene:ENSG00000211459;Name=MT-RNR1;biotype=M... 2514009 MT insdc gene 1671 3229 . + . ID=gene:ENSG00000210082;Name=MT-RNR2;biotype=M... 2514016 MT insdc gene 3307 4262 . + . ID=gene:ENSG00000198888;Name=MT-ND1;biotype=pr... 2514029 MT insdc gene 4470 5511 . + . ID=gene:ENSG00000198763;Name=MT-ND2;biotype=pr... 2514048 MT insdc gene 5904 7445 . + . ID=gene:ENSG00000198804;Name=MT-CO1;biotype=pr... 2514058 MT insdc gene 7586 8269 . + . ID=gene:ENSG00000198712;Name=MT-CO2;biotype=pr... 2514065 MT insdc gene 8366 8572 . + . ID=gene:ENSG00000228253;Name=MT-ATP8;biotype=p... 2514069 MT insdc gene 8527 9207 . + . ID=gene:ENSG00000198899;Name=MT-ATP6;biotype=p... 2514073 MT insdc gene 9207 9990 . + . ID=gene:ENSG00000198938;Name=MT-CO3;biotype=pr... 2514080 MT insdc gene 10059 10404 . + . ID=gene:ENSG00000198840;Name=MT-ND3;biotype=pr... 2514087 MT insdc gene 10470 10766 . + . ID=gene:ENSG00000212907;Name=MT-ND4L;biotype=p... 2514091 MT insdc gene 10760 12137 . + . ID=gene:ENSG00000198886;Name=MT-ND4;biotype=pr... 2514104 MT insdc gene 12337 14148 . + . ID=gene:ENSG00000198786;Name=MT-ND5;biotype=pr... 2514108 MT insdc gene 14149 14673 . - . ID=gene:ENSG00000198695;Name=MT-ND6;biotype=pr... 2514115 MT insdc gene 14747 15887 . + . ID=gene:ENSG00000198727;Name=MT-CYB;biotype=pr...
This example also shows how to combine two conditions during filtering with &
; the logical operator for “or” would be |
.
Note that the parentheses around each condition are required, and this part of the syntax in Pandas is different from Python, which would have been literal and
and or
.
Next, let's borrow the gdf
DataFrame from the previous section as a source for the length of each chromosome:
In [61]: gdf = gdf[gdf.seqid.isin(chrs)] In [62]: gdf.drop(['start', 'end', 'score', 'strand', 'phase' ,'attributes'], axis=1, inplace=True) In [63]: gdf.sort_values('length').ix[::-1] Out[63]: seqid source type length 0 1 GRCh38 chromosome 248956422 1364641 2 GRCh38 chromosome 242193529 1705855 3 GRCh38 chromosome 198295559 1864567 4 GRCh38 chromosome 190214555 1964921 5 GRCh38 chromosome 181538259 2080148 6 GRCh38 chromosome 170805979 2196981 7 GRCh38 chromosome 159345973 2514125 X GRCh38 chromosome 156040895 2321361 8 GRCh38 chromosome 145138636 2416560 9 GRCh38 chromosome 138394717 328938 11 GRCh38 chromosome 135086622 235068 10 GRCh38 chromosome 133797422 483370 12 GRCh38 chromosome 133275309 634486 13 GRCh38 chromosome 114364328 674767 14 GRCh38 chromosome 107043718 767312 15 GRCh38 chromosome 101991189 865053 16 GRCh38 chromosome 90338345 990810 17 GRCh38 chromosome 83257441 1155977 18 GRCh38 chromosome 80373285 1559144 20 GRCh38 chromosome 64444167 1201561 19 GRCh38 chromosome 58617616 2594560 Y GRCh38 chromosome 54106423 1647482 22 GRCh38 chromosome 50818468 1616710 21 GRCh38 chromosome 46709983 2513999 MT GRCh38 chromosome 16569
The columns that are not relevant to the analysis are dropped for clarity.
Yes, .drop
can also take a list of columns and drop them altogether in one operation.
Note that the row with a seqid of MT is still there; we will get back to it later. The next operation we will perform is merge the two datasets based on the values of seqid.
In [73]: cdf = chr_gene_counts.to_frame(name='gene_count').reset_index() In [75]: cdf.head(2) Out[75]: seqid gene_count 0 1 3902 1 2 2806 In [78]: merged = gdf.merge(cdf, on='seqid') In [79]: merged Out[79]: seqid source type length gene_count 0 1 GRCh38 chromosome 248956422 3902 1 10 GRCh38 chromosome 133797422 1600 2 11 GRCh38 chromosome 135086622 2561 3 12 GRCh38 chromosome 133275309 2140 4 13 GRCh38 chromosome 114364328 872 5 14 GRCh38 chromosome 107043718 1449 6 15 GRCh38 chromosome 101991189 1476 7 16 GRCh38 chromosome 90338345 1881 8 17 GRCh38 chromosome 83257441 2280 9 18 GRCh38 chromosome 80373285 766 10 19 GRCh38 chromosome 58617616 2412 11 2 GRCh38 chromosome 242193529 2806 12 20 GRCh38 chromosome 64444167 965 13 21 GRCh38 chromosome 46709983 541 14 22 GRCh38 chromosome 50818468 996 15 3 GRCh38 chromosome 198295559 2204 16 4 GRCh38 chromosome 190214555 1751 17 5 GRCh38 chromosome 181538259 2002 18 6 GRCh38 chromosome 170805979 2154 19 7 GRCh38 chromosome 159345973 2106 20 8 GRCh38 chromosome 145138636 1628 21 9 GRCh38 chromosome 138394717 1659 22 X GRCh38 chromosome 156040895 1852 23 Y GRCh38 chromosome 54106423 436
Since chr_gene_counts
is still a Series object, which doesn't support a merge operation, we need to convert it to a DataFrame object first with .to_frame
.
.reset_index()
converts the original index (ie seqid
) into a new column and resets current index as 0-based incremental numbers.
The output from cdf.head(2)
shows what it looks like. Next, we used the .merge
method to combine the two DataFrame on the seqid column ( on='seqid'
).
After merging gdf
and cdf
, the MT
entry is still missing. This is because, by default, .merge
operates an inner join, while left join, right join, or outer join are available by tuning the how
parameter.
Please refer to the documentation for more details.
Later, you may find that there is also a related .join
method. .merge
and .join
are similar yet have different APIs.
According to the official documentation says
The related DataFrame.join method, uses merge internally for the index-on-index and index-on-column(s) joins, but joins on indexes by default rather than trying to join on common columns (the default behavior for merge). If you are joining on index, you may wish to use DataFrame.join to save yourself some typing.
Basically, .merge
is more general-purpose and used by .join
.
Finally, we are ready to calculate the correlation between chromosome length
and gene_count
.
In [81]: merged[['length', 'gene_count']].corr() Out[81]: length gene_count length 1.000000 0.728221 gene_count 0.728221 1.000000
By default .corr
calculates the Pearson correlation between all pairs of columns in a dataframe.
But we have only a single pair of columns in this case, and the correlation turns out to be positive – 0.73.
In other words, the larger the chromosome, the more likely it is to have more genes. Let's also plot the two columns after sorting the value pairs by length
:
ax = merged[['length', 'gene_count']].sort_values('length').plot(x='length', y='gene_count',) # add some margin to both ends of x axis xlim = ax.get_xlim() margin = xlim[0] * 0.1 ax.set_xlim([xlim[0] - margin, xlim[1] + margin]) # Label each point on the graph for (s, x, y) in merged[['seqid', 'length', 'gene_count']].sort_values('length').values: ax.text(x, y - 100, str(s))
As seen in image above, even though it is a positive correlation overall, it does not hold for all chromosomes. In particular, for Chromosome 17, 16, 15, 14, 13, the correlation is actually negative, meaning the number of genes on the chromosome decreases as the chromosome size increases.
Findings and Future Research
That ends our tutorial on the manipulation of an annotation file for human genome in GFF3 format with the SciPy stack. The tools we've mainly used include IPython, Pandas, and matplotlib. During the tutorial, not only have we learned some of the most common and useful operations in Pandas, we also answered some very interesting questions about our genome. In summary:
- İlk taslak 15 yıl önce ortaya çıkmış olmasına rağmen, insan genomunun yaklaşık %0.37'si hala eksik.
- Kullandığımız bu özel GFF3 dosyasına dayalı olarak insan genomunda yaklaşık 42.000 gen var.
- Bir genin uzunluğu birkaç düzineden iki milyon baza kadar değişebilir.
- Genler kromozomlar arasında eşit olarak dağılmamıştır. Genel olarak, kromozom ne kadar büyükse, o kadar fazla gen barındırır, ancak kromozomların bir alt kümesi için korelasyon negatif olabilir.
GFF3 dosyası, açıklama bilgisi açısından çok zengindir ve biz sadece yüzeyi çizdik. Daha fazla keşifle ilgileniyorsanız, burada oynayabileceğiniz birkaç soru var:
- Bir genin tipik olarak kaç kopyası vardır? Genlerin yüzde kaçı 1'den fazla transkripte sahiptir?
- Bir transkript tipik olarak kaç izoforma sahiptir?
- Bir transkript tipik olarak kaç ekson, CDS ve UTR içerir? Hangi boyutlardalar?
- Tanımlama sütununda açıklandığı gibi genleri işlevlerine göre sınıflandırmak mümkün müdür?