Ich habe ein Standard-Diktat mit ~ 700 Tasten. Die Schlüssel haben ein Format wie A_B_STRING. Was ich tun muss, ist, den Schlüssel durch '_' zu teilen und den Abstand zwischen 'STRING' für jeden Schlüssel zu vergleichen, wenn A und B identisch sind. Wenn der Abstand < = 2 ist, möchte ich die Listen für diese Schlüssel in einem einzigen Standardschlüssel gruppieren: Wertgruppe. Es wird mehrere Schlüssel geben, die übereinstimmen und gruppiert werden sollen. Ich möchte auch in dem neuen kombinierten Standarddict alle Schlüssel: Wert-Paare behalten, die es nicht zu einer Gruppe gemacht haben.Python - Gruppierung defaultdict Werte durch Hamming Abstand in Tasten
Die Eingabedatei befindet sich im Format FASTA, wobei die Header die Schlüssel und die Werte die Sequenzen sind (defaultdict wird verwendet, da mehrere Sequenzen basierend auf einem Explosionsbericht aus einer ursprünglichen Fasta-Datei denselben Header haben). Diese
ist das, was ich bisher:
!/usr/bin/env python
import sys
from collections import defaultdict
import itertools
inp = sys.argv[1] # input fasta file; format '>header'\n'sequence'
with open(inp, 'r') as f:
h = []
s = []
for line in f:
if line.startswith(">"):
h.append(line.strip().split('>')[1]) # append headers to list
else:
s.append(line.strip()) # append sequences to list
seqs = dict(zip(h,s)) # create dictionary of headers:sequence
print 'Total Sequences: ' + str(len(seqs)) # Numb. total sequences in input file
groups = defaultdict(list)
for i in seqs:
groups['_'.join(i.split('_')[1:])].append(seqs[i]) # Create defaultdict with sequences in lists with identical headers
def hamming(str1, str2):
""" Simple hamming distance calculator """
if len(str1) == len(str2):
diffs = 0
for ch1, ch2 in zip(str1,str2):
if ch1 != ch2:
diffs += 1
return diff
keys = [x for x in groups]
combos = list(itertools.combinations(keys,2)) # Create tupled list with all comparison combinations
combined = defaultdict(list) # Defaultdict in which to place groups
for i in combos: # Combo = (A1_B1_STRING2, A2_B2_STRING2)
a1 = i[0].split('_')[0]
a2 = i[1].split('_')[0]
b1 = i[0].split('_')[1] # Get A's, B's, C's
b2 = i[1].split('_')[1]
c1 = i[0].split('_')[2]
c2 = i[1].split('_')[2]
if a1 == a2 and b1 == b2: # If A1 is equal to A2 and B1 is equal to B2
d = hamming(c1, c2) # Get distance of STRING1 vs STRING2
if d <= 2: # If distance is less than or equal to 2
combined[i[0]].append(groups[i[0]] + groups[i[1]]) # Add to defaultdict by combo 1 key
print len(combined)
for c in sorted(combined):
print c, '\t', len(combined[c])
Das Problem ist, dass dieser Code nicht wie erwartet funktioniert. Beim Drucken der Schlüssel im kombinierten Standarddict; Ich sehe deutlich, dass es viele gibt, die kombiniert werden können. Die Länge des kombinierten Standarddiktions ist jedoch etwa halb so groß wie das Original.
bearbeiten
Alternative keine itertools.combinations:
for a in keys:
tocombine = []
tocombine.append(a)
tocheck = [x for x in keys if x != a]
for b in tocheck:
i = (a,b) # Combo = (A1_B1_STRING2, A2_B2_STRING2)
a1 = i[0].split('_')[0]
a2 = i[1].split('_')[0]
b1 = i[0].split('_')[1] # Get A's, B's, C's
b2 = i[1].split('_')[1]
c1 = i[0].split('_')[2]
c2 = i[1].split('_')[2]
if a1 == a2 and b1 == b2: # If A1 is equal to A2 and B1 is equal to B2
if len(c1) == len(c2): # If length of STRING1 is equal to STRING2
d = hamming(c1, c2) # Get distance of STRING1 vs STRING2
if d <= 2:
tocombine.append(b)
for n in range(len(tocombine[1:])):
keys.remove(tocombine[n])
combined[tocombine[0]].append(groups[tocombine[n]])
final = defaultdict(list)
for i in combined:
final[i] = list(itertools.chain.from_iterable(combined[i]))
jedoch mit diesen Verfahren, bin ich immer noch ein paar aus, dass fehlende passen nicht alle anderen zu.
Sie vermissen ein "in Ihrer Hamming-Dokumentationszeichenfolge, es verursacht einen Formatierungsfehler, können Sie das dort einfügen? Ich würde es für Sie bearbeiten, aber Stapelüberlauf erfordert mindestens eine 6-stellige Bearbeitung:/ –
hat es geändert Irgendwelche Gedanken zu dem Thema, das ich habe? –