Search code examples
pythondictionarydefaultdict

Parsing Dictionary Into Spreadsheet in Python


I have some data in this similar format:

James has 6 jeans, 10 shirts, 5 shoes, 6 ties
Nick has 8 jeans, 4 shirts, 3 shoes, 4 ties
Adam has 2 jeans, 3 shirts, 5 shoes, 1 tie
John has 6 jeans, 5 shirts, 10 shoes, 3 ties

Using collections.defaultdict(list), I produced a dictionary in the follow format:

{James: [[Jeans, 6],
         [Shirts, 10],
         [Shoes, 5],
         [Ties, 6]],
 Nick: [[Jeans, 8],
        [Shirts, 4],
        [Shoes, 3],
        [Ties, 4]],
 Adam: [[Jeans, 2],
        [Shirts, 3],
        [Shoes, 5],
        [Ties, 1]],
 John: [[Jeans, 6],
        [Shirts, 5],
        [Shoes, 10],
        [Ties, 3]]}

I am trying to get this output in a cvs spreadsheet:

Accesories  James    Nick       Adam     John

Jeans         6       8           2        6

Shirts       10       4           3        5

Shoes        5        3           5        10

Ties         6        4           1         3

After doing some coding prior to build the dictionary, here is the code I have so far to try to produce a spreadsheet identical to format, above, using the dictionary that was created. cvs ,itertools modules are already imported.

with open(outputcsv, 'w') as w:
    writer = csv.writer(w, delimiter=',', lineterminator='\n')
    writer.writerow(dict.keys())

    zipped = itertools.izip_longest(*dict.values())
    writer.writerows(list(zipped))

This gets me fairly close to the intended solution but not quite.


Solution

  • This would be easier as a dict of dicts rather than a dict of list of lists.

    Assume:

    w={'James': {'Jeans': 6,
         'Shirts': 10,
         'Shoes': 5,
         'Ties': 6,},
     'Nick': {'Jeans': 8,
        'Shirts': 4,
        'Shoes': 3,
        'Ties': 4},
     'Adam': {'Jeans': 2,
        'Shirts': 3,
        'Shoes': 5,
        'Ties': 1},
     'John': {'Jeans': 6,
        'Shirts': 5,
        'Shoes': 10,
        'Ties': 3,
        'Belts': 1}}
    

    Notice John has a belt and the others do not and this is a dict of dicts rather than a dict of lists of two elements lists.

    First, let's get a list (ok, a set...) of all the accessories that anyone has:

    accessories=set()    
    for nam, di in w.items():
        for k in di:
            accessories.add(k)  
    >>> accessories
    set(['Ties', 'Belts', 'Jeans', 'Shirts', 'Shoes'])
    

    Now it is straightforward to create a CSV of these items in your format:

    import csv
    
    with open('/tmp/so.csv', 'w') as f:
        writer=csv.writer(f)
        writer.writerow(['accessories']+w.keys()) 
        for item in accessories:
            li=[item]
            for nam in w:
                li.append(w[nam].get(item, 0))
            writer.writerow(li)   
    

    Now look at the file:

    accessories,James,John,Adam,Nick
    Ties,6,3,1,4
    Belts,0,1,0,0
    Jeans,6,6,2,8
    Shirts,10,5,3,4
    Shoes,5,10,5,3
    

    If you are stuck with a dict of a list of lists each two elements (as you have in your example) you can convert them:

    >>> w={'James': [['Jeans', 6],
    ...      ['Shirts', 10],
    ...      ['Shoes', 5],
    ...      ['Ties', 6]],
    ...  'Nick': [['Jeans', 8],
    ...     ['Shirts', 4],
    ...     ['Shoes', 3],
    ...     ['Ties', 4]],
    ...  'Adam': [['Jeans', 2],
    ...     ['Shirts', 3],
    ...     ['Shoes', 5],
    ...     ['Ties', 1]],
    ...  'John': [['Jeans', 6],
    ...     ['Shirts', 5],
    ...     ['Shoes', 10],
    ...     ['Ties', 3],
    ...     ['Belts', 1]]}
    >>> {k:dict(LoL) for k, LoL in w.items()}
    {'James': {'Ties': 6, 'Jeans': 6, 'Shirts': 10, 'Shoes': 5}, 'John': {'Ties': 3, 'Belts': 1, 'Jeans': 6, 'Shirts': 5, 'Shoes': 10}, 'Adam': {'Ties': 1, 'Jeans': 2, 'Shirts': 3, 'Shoes': 5}, 'Nick': {'Ties': 4, 'Jeans': 8, 'Shirts': 4, 'Shoes': 3}}