Konstantin Rusanov
Konstantin Rusanov

Reputation: 6554

Convert list of dicts to CSV in Python 3

I got a list of dictionaries with different length and even different (key: values) pairs. For example:

[
    {'key1': 'value1', 'key3':'value3'},
    {'key1': 'someValue', 'key2':'value2', 'key3':'value3'},
    {'anotherKey': 'anotherValue', 'key1': 'value1', 'key2':'value2'},
    {'anotherKey': 'anotherValue', 'anotherKey1': 'anotherValue1', 'key1': 'value1', 'key2':'value2', 'key3':'value3'},
]

I need to create CSV file with all of keys as headers and values. If key not in the current dictionary then set the default value (for example '-'). The CSV from example should be looking like that:

enter image description here

I'm trying this code for my list of dictionaries, but it returns an error:

listOfDicts = [
    {'key1': 'value1', 'key3':'value3'},
    {'key1': 'someValue', 'key2':'value2', 'key3':'value3'},
    {'anotherKey': 'anotherValue', 'key1': 'value1', 'key2':'value2'},
    {'anotherKey': 'anotherValue', 'anotherKey1': 'anotherValue1', 'key1': 'value1', 'key2':'value2', 'key3':'value3'},
]

keys = listOfDicts[0].keys()
with open('test.csv', 'a') as output_file:
    dict_writer = csv.DictWriter(output_file, fieldnames=keys, delimiter='@')
    dict_writer.writeheader()
    dict_writer.writerows(listOfDicts)

ERROR:

ValueError: dict contains fields not in fieldnames: 'key2'

How I can add all unique keys as headers for CSV and fill it values by key?

Upvotes: 7

Views: 7949

Answers (2)

Raoslaw Szamszur
Raoslaw Szamszur

Reputation: 1740

Use DicitWritter() restval parameter,

The optional restval parameter specifies the value to be written if the dictionary is missing a key in fieldnames.

and for fieldnames parameter use a list of all available keys in a list of dictionaries.

import csv


listOfDicts = [
    {'key1': 'value1', 'key3':'value3'},
    {'key1': 'someValue', 'key2':'value2', 'key3':'value3'},
    {'anotherKey': 'anotherValue', 'key1': 'value1', 'key2':'value2'},
    {'anotherKey': 'anotherValue', 'anotherKey1': 'anotherValue1', 'key1': 'value1', 'key2':'value2', 'key3':'value3'},
]

keys = [i for s in [d.keys() for d in listOfDicts] for i in s]

with open('test.csv', 'a') as output_file:
    dict_writer = csv.DictWriter(output_file, restval="-", fieldnames=keys, delimiter='@')
    dict_writer.writeheader()
    dict_writer.writerows(listOfDicts)

output:

$ cat test.csv 
key3@key1@key2@anotherKey@anotherKey1
value3@value1@-@-@-
value3@someValue@value2@-@-
-@value1@value2@anotherValue@-
value3@value1@value2@anotherValue@anotherValue1

Reference: https://docs.python.org/2/library/csv.html#csv.DictWriter

Upvotes: 10

Ralf
Ralf

Reputation: 16505

To overcome the error, you can collect all the keys before writing the file, like this:

keys = set()
for d in listOfDicts:
    keys.update(d.keys())

with open('test.csv', 'a') as output_file:
    dict_writer = csv.DictWriter(
        output_file, fieldnames=keys, restval='-', delimiter='@')
    dict_writer.writeheader()
    dict_writer.writerows(listOfDicts)

You can use the parameter DictWriter.restval to assign default values for missing keys.

Upvotes: 3

Related Questions