2016-04-25 1 views
1

У меня есть следующий ДИКТ:печати вложенное Dict для 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}} 

Моей желаемый выхода является:

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 

Как можно заметить, если любое подмножество пропускает 'счетчик' , нуль должен занять место. Я пробовал разные способы сделать это, но я не могу этого добиться. Я в состоянии сделать печать с простым Dict, но не с вложенной один:

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

Вы знаете все возможные ключи вложенных словарей фронтов или это должно быть автоматически обнаружено из этих ключей? –

+0

Вы ссылаетесь на "A1137 A2160 A2579 A2594"? – cucurbit

+0

Нет, 'Called',' hom_alt', 'hom_ref' и' private_hom'. –

ответ

1

Это проще с помощью csv.DictWriter(), где вы проходите в словарь для каждой строки.

Вы можете автоматически открывать ключи в словарях, создавая объединение всех содержащихся словарей (которые вытаскивают ключи); эти stats значение в вашем выводе:

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) 

Демо:

>>> 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

Большое спасибо @Martijn. У меня вопрос, возможно ли «поддерживать порядок» dict? Я имею в виду, что в данном случае A1137, A2160, A2579, A2594 сортируются, но представьте, что A1137 назван A3137, поэтому наши ключи: A3137, A2160, A2579, A2594. Возможно ли иметь таблицу вывода в этом порядке? – cucurbit

+0

@cucurbit: нет, потому что словари не имеют порядка. Это неупорядоченные структуры. См. [Почему порядок в словарях и наборах Python произволен?] (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)) 
Смежные вопросы