2015-11-27 16 views
6

Supponiamo che io ho l'elenco dei set di dati dizionario come questo,Write elenco di dizionario in CSV Python

data_set = [ 
    {'Active rate': [0.98, 0.97, 0.96]}, 
    {'Operating Expense': [3.104, 3.102, 3.101]} 
] 

ho bisogno di iterare l'elenco dei dizionario e mettere le chiavi come intestazioni delle colonne e dei suoi valori come righe e scrivilo nel file CSV.

Active rate Operating Expense 
0.98   3.104 
0.97   3.102 
0.96   3.101 

Questo è quello che ho cercato

data_set = [ 
    {'Active rate': [0.98, 0.931588, 0.941192]}, 
    {'Operating Expense': [3.104, 2.352, 2.304]} 
] 

import csv 

with open('names.csv', 'w') as csvfile: 
    fieldnames = ['Active rate', 'Operating Expense'] 
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames) 

    writer.writeheader() 
    writer.writerow({'Active rate': 0.98, 'Operating Expense': 3.102}) 
    writer.writerow({'Active rate': 0.97, 'Operating Expense': 3.11}) 
    writer.writerow({'Active rate': 0.96, 'Operating Expense': 3.109}) 

Per brevità, ho ridotto le chiavi per 2 e un elenco di valori a 3.

Come affrontare questo problema?

Grazie

+4

Qual è il vero problema? – thefourtheye

+0

Vuoi sapere come scrivere ogni riga in qualche modo automaticamente invece di mettere insieme i valori manualmente? – albert

+0

Sì. Ho bisogno di sapere come scrivere automaticamente ogni riga. – PyAn

risposta

2
data_set = [ 
    {'Active rate': [0.98, 0.97, 0.96]}, 
    {'Operating Expense': [3.104, 3.102, 3.101]} 
] 

In primo luogo, solo un rapido commento, la tua struttura dati iniziale non ha necessariamente un senso così com'è. Stai usando un elenco di dict, ma ogni parola sembra utilizzare solo una chiave, che sembra sconfiggere il suo scopo.

Altre strutture dati che avrebbero più senso sarebbe qualcosa del genere (dove ogni struttura dict viene utilizzata, come è attualmente, per una coppia etichetta/valore, ma almeno il dict viene usato per indicare l'etichetta e il valore):

data_set = [ 
    {'label': 'Active rate', 'values': [0.98, 0.97, 0.96]}, 
    {'label': 'Operating Expense', 'values': [3.104, 3.102, 3.101]} 
] 

o, forse meglio, un OrderedDict che ti danno sia l'ordine dei dati iniziali quali definiti ed i benefici di mappatura chiave/valore:

from collections import OrderedDict 
data_set = OrderedDict() 
data_set['Active rate'] = [0.98, 0.97, 0.96] 
data_set['Operating Expense'] = [3.104, 3.102, 3.101] 

Naturalmente, noi don' t sempre scegliere le strutture di dati che otteniamo, quindi assumiamo che c non lo cambia La tua domanda diventa quindi un problema di scambio dei ruoli di righe e colonne dal set di dati iniziale. Effettivamente, si desidera eseguire iterazioni su più elenchi contemporaneamente e, per questo, zip è molto utile.

import csv 

fieldnames = [] 
val_lists = [] 
for d in data_set: 
    # Find the only used key. 
    # This is a bit awkward because of the initial data structure. 
    k = d.keys()[0] 
    fieldnames.append(k) 
    val_lists.append(d[k]) 

with open('names.csv', 'w') as csvfile: 
    writer = csv.writer(csvfile)  
    writer.writerow(fieldnames) 

    for row in zip(*val_lists): 
     # This picks one item from each list and builds a list. 
     # The first row will be [0.98, 3.104] 
     # The second row will be [0.97, 3.102] 
     # ... 
     writer.writerow(row) 

Si noti che non v'è alcun bisogno di una DictWriter quando si utilizza zip, in quanto ciò significherebbe è necessario ricostruire un dict, senza alcun beneficio reale.

+0

Si potrebbe anche fare l'ultima parte in modo più conciso usando 'writerows (zip (* val_lists))' come suggerito da @MartinEvans. – Bruno

3

L'approccio seguito dovrebbe funzionare per la struttura dei dati che hai dato:

import csv 

data_set = [ 
    {'Active rate': [0.98, 0.97, 0.96]}, 
    {'Operating Expense': [3.104, 3.102, 3.101]} 
] 

fieldnames = ['Active rate', 'Operating Expense'] 
rows = [] 

for field in fieldnames: 
    for data in data_set: 
     try: 
      rows.append(data[field]) 
      break 
     except KeyError, e: 
      pass 

with open('names.csv', 'wb') as f_output: 
    csv_output = csv.writer(f_output) 
    csv_output.writerow(fieldnames) 
    csv_output.writerows(zip(*rows)) 

Dandovi il seguente file di output CSV:

Active rate,Operating Expense 
0.98,3.104 
0.97,3.102 
0.96,3.101 
3
d1 = {'Active rate': [0.98, 0.931588, 0.941192]} 
d2 = {'Operating Expense': [3.104, 2.352, 2.304]} 

with open('names.csv', 'w') as csvfile: 
    fieldnames = zip(d1, d2)[0] 
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames) 
    writer.writeheader() 

    for row in zip(d1['Active rate'], d2['Operating Expense']): 
     writer.writerow(dict(zip(fieldnames, row))) 

Per le prestazioni, si potrebbe desiderare di utilizzare itertools.izip sopra zip a seconda della lunghezza delle liste.

+1

'itertools.izip' è davvero un buon suggerimento per dataset più grandi. (Probabilmente causerebbe problemi per la sostituzione di 'zip (d1, d2) [0]' a causa dell'indice, ma ciò non dovrebbe essere difficile da correggere – Bruno

3

(Questa risposta ha lo svantaggio di usare una libreria esterna, ma)

pandas fornisce già straordinariamente strumenti potenti e semplici per trattare con i file CSV. È possibile utilizzare to_csv.

Nota la struttura dei dati è strutturata goffamente, così abbiamo prima trasformarlo in una struttura più intuitiva

data_set2 = { x.keys()[0] : x.values()[0] for x in data_set } 

import pandas as pd 
df = pd.DataFrame(data_set2) 
df.to_csv('names.csv', index = False) 
+0

@Bruno, giusto! Grazie. Risolto ora. Quindi se il downvote è a causa del bug ... – shx2

+1

Qualcun altro deve avere downvoted, puoi solo sperare che torni a controllare. – Bruno

2

Questo codice vi aiuterà senza essere legato ad un certo numero di dicts all'interno data_set

ho aggiunto un altro dict con il tasto 'perdite', per testare

import csv 

data_set = [ 
    {'Active rate': [0.98, 0.97, 0.96]}, 
    {'Operating Expense': [3.104, 3.102, 3.101]}, 
    {'Losses': [1.14, 2.28, 3.42]} 
] 

headers = [d.keys()[0] for d in data_set] 

with open('names.csv', 'w') as csvfile: 
    writer = csv.DictWriter(csvfile, fieldnames=headers) 
    writer.writeheader() 
    for item in zip(*[x.values()[0] for x in data_set]): 
     more_results = list() 
     more_results.append(headers) 
     more_results.append(item) 
     writer.writerow(dict(zip(*more_results))) 

uscita:

enter image description here

+1

"* Questo codice ti aiuterà senza essere legato a un certo numero di dicts all'interno di data_set *": Penso che la maggior parte altro le risposte stavano già prendendo in considerazione questo: – Bruno

+0

@Bruno Non scrivo codice in base ad altre risposte.Grazie per il tuo suggerimento comunque. –

+0

Puoi farlo compatibile con Python 3? – PyAn