2015-04-08 1 views
-2

J'ai deux dictionnaires:Comparaison des clés de dictionnaire avec des tolérances

d1 = {'100.1125': '353.2216'; '151.0977': '131.2193'; '102.0553': '103.6859'; '103.0209': '104.624'} 

d2 = {'100.1124': '352.2220'; '200': '131.2193'; '300': '103.6859'; '400': '104.624'; '103.0545': '448.3161'} 

Je souhaite faire une boucle par touches d1 et vérifier leur présence dans d2, +/- une tolérance spécifiée. Si vrai, je souhaite ensuite comparer les valeurs associées pour chaque clé de dictionnaire et vérifier si elles correspondent également à une tolérance donnée. Quand une correspondance est trouvée, je voudrais écrire la sortie dans un fichier (Output_match.txt). Quand aucune correspondance n'est trouvée, je voudrais écrire la clé d1 et la valeur associée dans un deuxième fichier (Output_nomatch.txt). Donc, supposons que la tolérance pour la comparaison des dictionnaires soit +/- 0.0002. La tolérance pour la comparaison de valeurs est +/- 5.

Je me attends Output_match.txt contenir:

key ---- value 
100.1125 ---- 353.2216 

Je me attends Output_nomatch.txt contenir:

key ---- value 
151.0977 ---- 131.2193 
102.0553 ---- 103.6859 
103.0209 ---- 104.624 

personne pourrait offrir une aide ici?

EDIT:

Toutes mes excuses pour ne pas avoir fourni mon actuelle tentative:

with open(os.path.join(path,'out_true.txt'), 'w') as opt_true, open(os.path.join(path,'out_false.txt'), 'w') as opt_false: 
header = ('%s\t%s\t%s\t%s\n') % ('file1_mz', 'file1_rt', 'file2_mz', 'file2_rt') 
opt_true.write(header) 
for key in d1.keys(): 
    upper_mz = float(key) + (float(key) * (ppm*0.000001)) 
    lower_mz = float(key) - (float(key) * (ppm*0.000001)) 
    upper_rt = float(dict1[key]) + (2*rt_shift) 
    lower_rt = float(dict1[key]) - (2*rt_shift) 
    for key2 in d2: 
     upper_mz2 = float(key2) + (float(key2) * (ppm*0.000001)) 
     lower_mz2 = float(key2) - (float(key2) * (ppm*0.000001)) 
     upper_rt2 = float(dict2[key2]) + (2*rt_shift) 
     lower_rt2 = float(dict2[key2]) - (2*rt_shift) 
     if float(upper_mz) >= float(lower_mz2) and float(lower_mz) <= float(upper_mz2) and float(upper_rt) >= float(lower_rt2) and float(lower_rt) <= float(upper_rt2): 
      opt_true.write(('%s\t%s\t%s\t%s\n') % (str(key), str(dict1[key]), str(key2), str(dict2[key2]))) 
      #print float(key) 
      a[key] = d1[key] 
      b[key2] = d2[key2] 
for key in d1.keys(): 
    if not key in a: 
     opt_false.write(('%s\t%s\n') % (str(key), d1[key])) 
for key2 in d2.keys(): 
    if not key2 in b: 
     opt_false.write(('%s\t%s\n') % (str(key), d1[key])) 

opt_true.close() 
opt_false.close() 
+1

Ce n'est pas un service de tutoriel; Où est votre implémentation, et quel est le problème? – jonrsharpe

+1

Que faire s'il y a plusieurs correspondances pour la même clé? Est-ce que la clé et la valeur de 'd1' doivent être écrites dans' Output_match.txt' plus d'une fois? par exemple. pour la tolérance 0.1, la clé 'd1 = 100.0' et les touches' 100.01' et '99.99' dans' d2', la clé de 'd1' serait sortie deux fois. – mhawke

+0

@mhawke vous avez absolument raison, et j'aurais dû préciser cette possibilité dans mon message original. Il est possible que certaines touches de d1 chevauchent plusieurs touches dans d2. – MRJ

Répondre

1

Vous pouvez essayer quelque chose comme cela, en utilisant la fonction intégrée abs, afin de calculer la distance dans un simple chemin:

d1 = {'100.1125': '353.2216', '151.0977': '131.2193', 
     '102.0553': '103.6859', '103.0209': '104.624'} 
d2 = {'100.1124': '352.2220', '200': '131.2193', 
     '300': '103.6859', '400': '104.624', '103.0545': '448.3161'} 

key_tolerance, value_tolerance = 0.0002, 5 
output_match, output_nomatch = [], [] 

for i, j in d1.items(): 
    for k, l in d2.items(): 
     if (abs(float(i)-float(k)) <= key_tolerance and 
      abs(float(j)-float(l)) <= value_tolerance): 
      output_match.append((i, j)) 
     else: 
      output_nomatch.append((i, j)) 

print(output_match, '----', set(output_nomatch) - set(output_match), sep='\n') 

sortie:

[('100.1125', '353.2216')] 
---- 
{('102.0553', '103.6859'), 
('103.0209', '104.624'), 
('151.0977', '131.2193')}