Python: написание вложенного словаря в CSV

Я пытаюсь написать вложенный словарь для a .CSV-файл. Вот простой пример:

import csv
import itertools

fields = [ 'org', '2015', '2014', '2013' ]
dw     = { 'orgname1': { '2015' : 2, '2014' : 1, '2013' : 1 },
           'orgname2': { '2015' : 1, '2014' : 2, '2013' : 3 },
           'orgname3': { '2015' : 1, '2014' : 3, '2013' : 1 }
        }

with open("test_output.csv", "wb") as f:
    w = csv.writer( f )
    years = dw.values()[0].keys()
    for key in dw.keys():
        w.writerow([key, [dw[key][year] for year in years]])

Это дает мне таблицу с двумя столбцами: первый содержит orgname; второй содержит [2, 1, 1] (или соответствующие значения из суб-словарь). Мне нужна таблица с четырьмя столбцами: один для orgname и потом три для соответствующих элементов списка.

4 ответов


изменения:

w.writerow([key, [dw[key][year] for year in years]])

в:

w.writerow([key] + [dw[key][year] for year in years])

в противном случае вы пытаетесь написать что-то вроде [orgname1, [2, 1, 1]] в csv, в то время как вы имеете в виду [orgname1, 2, 1, 1].

как упоминал Падрайк, вы можете изменить years = dw.values()[0].keys() до years = sorted(dw.values()[0].keys()) или years = fields[1:] чтобы избежать случайного поведения.


Это похоже на работу для DictWriter:

import csv
import itertools
import sys

fields = [ 'org', '2015', '2014', '2013' ]
dw     = { 'orgname1': { '2015' : 2, '2014' : 1, '2013' : 1 },
           'orgname2': { '2015' : 1, '2014' : 2, '2013' : 3 },
           'orgname3': { '2015' : 1, '2014' : 3, '2013' : 1 }
        }

w = csv.DictWriter( sys.stdout, fields )
for key,val in sorted(dw.items()):
    row = {'org': key}
    row.update(val)
    w.writerow(row)

альтернативная реализация с использованием DictWriter и с заголовками

import csv
import itertools

fields = [ 'org', '2015', '2014', '2013' ]
dw     = { 'orgname1': { '2015' : 2, '2014' : 1, '2013' : 1 },
           'orgname2': { '2015' : 1, '2014' : 2, '2013' : 3 },
           'orgname3': { '2015' : 1, '2014' : 3, '2013' : 1 }
        }

with open("test_output.csv", "wb") as f:
    w = csv.DictWriter(f, fields)
    w.writeheader()
    for k in dw:
        w.writerow({field: dw[k].get(field) or k for field in fields})

выход:

org,2015,2014,2013
orgname1,2,1,1
orgname3,1,3,1
orgname2,1,2,3

использование DictWriter нет необходимости в сортировке полей заранее, так как w.writerow() обеспечит правильный порядок. Но есть смысл сортировать сами предметы.

поэтому, собирая все вышеперечисленные предложения и выбирая лучшее из каждого, я бы придумал следующий код:

import csv
import itertools

def mergedict(a,b):
    a.update(b)
    return a

fields = [ 'org', '2015', '2014', '2013' ]
dw     = { 'orgname1': { '2015' : 2, '2014' : 1, '2013' : 1 },
           'orgname2': { '2015' : 1, '2014' : 2, '2013' : 3 },
           'orgname3': { '2015' : 1, '2014' : 3, '2013' : 1 }
        }

with open("test_output.csv", "wb") as f:
    w = csv.DictWriter( f, fields )
    w.writeheader()
    for k,d in sorted(dw.items()):
        w.writerow(mergedict({'org': k},d))

я добавляю крошечную mergedict() функция которая делает им один вкладыш дальше вниз.