precicely
precicely

Reputation: 531

How to sort uneven dictionary by key and create CSV

I have a python dictionary which for each KEY one can have a variable number of VALUES (arranged in a list).

For example:

{'607': [36146], '448': [50890, 44513], '626': [44349, 44436]}

What I'd like to do is generate a CSV of this information with a format like so:

 448 , 607 , 626
50890,36146,44349
44513,     ,44436

Currently my code can produce a CSV such as this, the only issue being that the columns of the CSV are not sorted according to the ascending numerical order of the KEYs. My code so far is below:

csv_file = 'file.csv'
with open(csv_file, 'wb') as fd:
    writer = csv.writer(fd, delimiter = ',')

    # Format headers for aesthetics
    csv_headers = [' {} '.format(elem) for elem in dictionary.keys()]

    writer.writerow(headers)

    # Format data to create convenient csv format
    csv_data = itertools.izip_longest(*dictionary.values(), fillvalue = '     ')
    writer.writerows(csv_data)

As you can see I split the KEYs from the VALUEs and write them separately but if I want to sort the columns by the KEYs I imagine this is probably not the best way to go about this. Therefore, I was hoping someone could point me in the right (and most pythonic) direction.

Upvotes: 0

Views: 1604

Answers (2)

Jon Clements
Jon Clements

Reputation: 142216

I went for sorting and ending up with a transposed tuple of key and an iterable of the lists, then went from there:

import csv
from itertools import izip_longest

d = {'607': [36146], '448': [50890, 44513], '626': [44349, 44436]}

with open('output.csv', 'wb') as fout:
    csvout = csv.writer(fout)
    header, rows = zip(*sorted((k, iter(v)) for k, v in d.iteritems()))
    csvout.writerow(format(el, '^5') for el in header)
    csvout.writerows(izip_longest(*rows, fillvalue='     '))

Upvotes: 1

Martijn Pieters
Martijn Pieters

Reputation: 1123640

You have two options:

  • Sort the keys, then extract values in the same order rather than rely on dictionary.values()
  • Use a csv.DictWriter() object and produce dictionaries per row.

Option 1 looks like this:

csv_file = 'file.csv'
with open(csv_file, 'wb') as fd:
    writer = csv.writer(fd, delimiter=',')

    keys = sorted(dictionary) 
    # Format headers for aesthetics
    headers = [' {} '.format(key) for key in keys]
    writer.writerow(headers)

    # Format data to create convenient csv format
    csv_data = itertools.izip_longest(*(dictionary[key] for key in keys),
                                      fillvalue='     ')
    writer.writerows(csv_data)

Using DictWriter would look like:

csv_file = 'file.csv'
with open(csv_file, 'wb') as fd:
    writer = csv.DictWriter(
        fd, sorted(dictionary), delimiter=',')
    # write formatted headers
    writer.writerow({k: ' {} '.format(k) for k in dicitonary})

    csv_data = itertools.izip_longest(*dictionary.values(), fillvalue='     ')
    writer.writerows(dict(zip(dictionary, row)) for row in csv_data)

Upvotes: 2

Related Questions