2013-08-27 2 views
1

Je veux comparer plusieurs fichiers (15-20), qui sont gzippés, et restaurer à partir de ces lignes, qui sont communs. Mais ce n'est pas si simple. Les lignes qui sont exactes dans certaines colonnes, et aussi je voudrais avoir pour eux compte des informations dans combien de fichiers ils étaient présents. Si 1, la ligne est unique à un fichier, etc. Serait également agréable de conserver ces noms de fichiers.Comparaison de plusieurs fichiers

chaque fichier ressemble st comme ceci:

##SAMPLE=<ID=NormalID,Description="Cancer-paired normal sample. Sample ID 'NORMAL'"> 
##SAMPLE=<ID=CancerID,Description="Cancer sample. Sample ID 'TUMOR'"> 
#CHROM POS  ID  REF  ALT  QUAL FILTER INFO FORMAT NormalID_NORMAL CancerID_TUMOR 
chrX 136109567  .  C  CT  .  PASS IC=8;IHP=8;NT=ref;QSI=35;QSI_NT=35;RC=7;RU=T;SGT=ref->het;SOMATIC;TQSI=1;TQSI_NT=1;phastCons;CSQ=T|ENSG00000165370|ENST00000298110|Transcript|5KB_downstream_variant|||||||||YES|GPR101|||||  DP:DP2:TAR:TIR:TOR:DP50:FDP50:SUBDP50 23:23:21,21:0,0:2,2:21.59:0.33:0.00 33:33:16,16:13,13:4,4:33.38:0.90:0.00 
chrX 150462334  .  T  TA  .  PASS IC=2;IHP=2;NT=ref;QSI=56;QSI_NT=56;RC=1;RU=A;SGT=ref->het;SOMATIC;TQSI=2;TQSI_NT=2;CSQ=A||||intergenic_variant||||||||||||||| DP:DP2:TAR:TIR:TOR:DP50:FDP50:SUBDP50 30:30:30,30:0,0:0,0:31.99:0.00:0.00  37:37:15,17:16,16:6,5:36.7:0.31:0.00 

Les fichiers sont délimités par des tabulations. Si la ligne commence par #, ignorez cette ligne. Nous ne sommes intéressés que par ceux qui ne le font pas. En prenant 0 coordonnées python, nous nous intéressons aux champs 0,1,2,3,4. Ils doivent correspondre entre les fichiers à signaler comme commun. Cependant, nous avons encore besoin tohold d'informations sur le reste des coulmns/champs, afin qu'ils puissent être écrits tot il fichier de sortie

En ce moment, je le code suivant:

import gzip 
filenames = ['a','b','c'] 
files = [gzip.open(name) for name in filenames] 

sets = [set(line.strip() for line in file if not line.startswith('#')) for file in files] 
common = set.intersection(*sets) 
for file in files: file.close() 
print common 

Dans mon code currenyt je Je ne sais pas comment implémenter correctement le if sinon line.startswith() (quel endroit?), et comment spécifier les colonnes en ligne qui doivent correspondre. Sans oublier que je n'ai aucune idée de comment obtenir les lignes qui sont par exemple présentes dans 6 fichiers, ou présentes dans 10 des 15 fichiers au total. Une aide avec cette fonction?

Répondre

1

Recueillir les lignes dans un dictionnaire avec les champs qui les rendent similaires comme la clé:

from collections import defaultdict 
d = defaultdict(list) 

def process(filename, line): 
    if line[0] == '#': 
     return 

    fields = line.split('\t') 
    key = tuple(fields[0:5]) # Fields that makes lines similar/same 
    d[key].append((filename, line)) 

for filename in filenames: 
    with gzip.open(filename) as fh: 
     for line in fh: 
      process(filename, line.strip()) 

Maintenant, vous avez un dictionnaire avec des listes de tuples nom de fichier ligne. Vous pouvez maintenant imprimer toutes les lignes qui apparaissent plus de 10 fois:

for l in d.values(): 
    if len(l) < 10: continue 

    print 'Same key found %d times:' % len(l) 

    for filename, line in l: 
     print '%s: %s' % (filename, line) 
+0

J'ai un problème suivant: TypeError: Type unhashable: « liste » dans les lignes: d [key] .append et processus (nom de fichier [.. – Irek

+0

Ah, oui, essayez 'key = tuple (champs [0: 5])' –

+0

Ceci est une excellente réponse, et le concept a été compris dès le début.Je jouerai autour de moi avec la belle sortie (entre le courant on est déjà très gentil et permet un filtrage très facile). – Irek

Questions connexes