2016-04-25 11 views
1

Ich habe folgendes dict:Druck dict verschachtelte Formatdatei tsv

{'A1137': {'Called': 10, 'hom_alt': 10, 'private_hom': 8}, 
'A2160': {'Called': 10, 'hom_alt': 1, 'hom_ref': 9}, 
'A2579': {'Called': 10, 'hom_alt': 1, 'hom_ref': 9}, 
'A2594': {'Called': 9, 'hom_alt': 1, 'hom_ref': 8}} 

Mein Wunsch Ausgang ist:

stats A1137 A2160 A2579 A2594 
Called 10 10 10 9 
hom_alt 10 1 1 1 
hom_ref 0 9 9 8 
private_hom 8 0 0 0 

Wie beobachtet werden kann, wenn eine Teilmenge ein 'Zähler' vermisst eine Null sollte den Platz einnehmen. Ich habe verschiedene Möglichkeiten ausprobiert, aber ich kann es nicht erreichen. Ich bin in der Lage, den Druck mit einem einfachen dict zu tun, aber nicht mit einem verschachtelten ein:

with open(res, 'w') as csvfile: 
    w = csv.writer(csvfile, delimiter='\t') 
    w.writerow(['#Global Statistics:']) 
    for key, value in d.items(): 
     w.writerow([key, value]) 
    w.writerow(['\n']) 
return res 
+0

Kennen Sie alle möglichen Schlüssel in dem verschachtelten Wörterbücher vorne oder dass aus diesem Schlüssel automatisch erkannt werden sollte? –

+0

Beziehen Sie sich in diesem Fall auf "A1137 A2160 A2579 A2594"? – cucurbit

+0

Nein, 'Called',' hom_alt', 'hom_ref' und' private_hom'. –

Antwort

1

Dies ist einfacher csv.DictWriter() verwenden, in dem Sie für jede Zeile in einem Wörterbuch übergeben.

Sie könnten die Schlüssel in den Wörterbüchern automatisch erkennen, indem Sie die Vereinigung aller enthaltenen Wörterbücher erstellen (die die Schlüssel herausziehen); das sind die stats Werte in Ihrer Ausgabe:

fields = sorted(d) 
stats = sorted(set().union(*d.values())) # use d.itervalues() in Python 2 

with open(res, 'w') as csvfile: 
    w = csv.DictWriter(csvfile, delimiter='\t', fieldnames=['stats'] + fields) 
    w.writerow({'stats': '#Global Statistics:'}) 
    w.writeheader() 
    for stat in stats: 
     # produce a dictionary mapping field name to specific statistic for 
     # this row 
     row = {k: v.get(stat, 0) for k, v in d.items()} 
     row['stats'] = stat 
     w.writerow(row) 

Demo:

>>> import csv 
>>> import sys 
>>> d = {'A1137': {'Called': 10, 'hom_alt': 10, 'private_hom': 8}, 
...  'A2160': {'Called': 10, 'hom_alt': 1, 'hom_ref': 9}, 
...  'A2579': {'Called': 10, 'hom_alt': 1, 'hom_ref': 9}, 
...  'A2594': {'Called': 9, 'hom_alt': 1, 'hom_ref': 8}} 
>>> fields = sorted(d) 
>>> stats = sorted(set().union(*d.values())) 
>>> w = csv.DictWriter(sys.stdout, delimiter='\t', fieldnames=['stats'] + fields) 
>>> w.writerow({'stats': '#Global Statistics:'}) 
#Global Statistics: 
>>> w.writeheader() 
stats A1137 A2160 A2579 A2594 
>>> for stat in stats: 
...  # produce a dictionary mapping field name to specific statistic for 
...  # this row 
...  row = {k: v.get(stat, 0) for k, v in d.items()} 
...  row['stats'] = stat 
...  w.writerow(row) 
... 
Called 10  10  10  9 
hom_alt 10  1  1  1 
hom_ref 0  9  9  8 
private_hom  8  0  0  0 
+0

Vielen Dank @Martijn. Ich habe eine Frage, ist es möglich, die Ordnung des Diktats aufrechtzuerhalten? Ich meine, in diesem speziellen Fall sind A1137, A2160, A2579, A2594 sortiert, aber stellen Sie sich vor, dass A1137 als A3137 benannt ist, also unsere Schlüssel sind: A3137, A2160, A2579, A2594. Ist es möglich, die Ausgabetabelle in dieser Reihenfolge zu haben? – cucurbit

+0

@cucurbit: Nein, weil Wörterbücher keine Reihenfolge haben. Sie sind ungeordnete Strukturen. Siehe [Warum ist die Reihenfolge in Python-Wörterbüchern und -Sätzen frei wählbar?] (Https://stackoverflow.com/a/15479974) –

1
from collections import defaultdict 

data = { 
'A1137': {'Called': 10, 'hom_alt': 10, 'private_hom': 8}, 
'A2160': {'Called': 10, 'hom_alt': 1, 'hom_ref': 9}, 
'A2579': {'Called': 10, 'hom_alt': 1, 'hom_ref': 9}, 
'A2594': {'Called': 9, 'hom_alt': 1, 'hom_ref': 8} 
} 

fields = "stats","Called","hom_alt","hom_ref","private_hom" 

newdata = list() 
for (k,v) in data.items(): 
    d = defaultdict(int) 
    d.update(v) 
    d["stats"] = k 
    newdata.append(d) 

table = [fields] 
for d in newdata: 
    table.append([d[f] for f in fields]) 

#first, a pretty print 
fmt = "{:<11}" + "{:>6}" * (len(d) - 1) 
for row in zip(*table): 
    print(fmt.format(*row)) 

tsvfmt = "\t".join(["{}"]*len(d)) 
for row in zip(*table): 
    print(tsvfmt.format(*row))