Agregar cabecera pitónicamente a un archivo csv

84

Escribí un script de Python fusionando dos archivos csv, y ahora quiero agregar un encabezado al csv final. Traté de seguir las sugerencias reportados aquí y me dio el siguiente error: expected string, float found. ¿Cuál es la forma más pitónica de solucionar esto?

Aquí está el código que estoy usando:

import csv

with open('combined_file.csv', 'w', newline='') as outcsv:
    writer = csv.DictWriter(outcsv, fieldnames = ["Date", "temperature 1", "Temperature 2"])
    writer.writeheader()

    with open('t1.csv', 'r', newline='') as incsv:
        reader = csv.reader(incsv)
        writer.writerows(row + [0.0] for row in reader)

    with open('t2.csv', 'r', newline='') as incsv:
        reader = csv.reader(incsv)
        writer.writerows(row[:1] + [0.0] + row[1:] for row in reader)
albus_c
fuente
¿cuántas columnas está escribiendo en su archivo csv? ¿Podría especificar en su pregunta 1. formato de entrada de su archivo 2. formato de salida
nio
@nio: Una gran parte del código publicado es de esta pregunta anterior del OP
Martijn Pieters

Respuestas:

115

La DictWriter()clase espera diccionarios para cada fila. Si todo lo que quería hacer era escribir un encabezado inicial, use un regular csv.writer()y pase en una fila simple para el encabezado:

import csv

with open('combined_file.csv', 'w', newline='') as outcsv:
    writer = csv.writer(outcsv)
    writer.writerow(["Date", "temperature 1", "Temperature 2"])

    with open('t1.csv', 'r', newline='') as incsv:
        reader = csv.reader(incsv)
        writer.writerows(row + [0.0] for row in reader)

    with open('t2.csv', 'r', newline='') as incsv:
        reader = csv.reader(incsv)
        writer.writerows(row[:1] + [0.0] + row[1:] for row in reader)

La alternativa sería generar diccionarios al copiar sus datos:

import csv

with open('combined_file.csv', 'w', newline='') as outcsv:
    writer = csv.DictWriter(outcsv, fieldnames = ["Date", "temperature 1", "Temperature 2"])
    writer.writeheader()

    with open('t1.csv', 'r', newline='') as incsv:
        reader = csv.reader(incsv)
        writer.writerows({'Date': row[0], 'temperature 1': row[1], 'temperature 2': 0.0} for row in reader)

    with open('t2.csv', 'r', newline='') as incsv:
        reader = csv.reader(incsv)
        writer.writerows({'Date': row[0], 'temperature 1': 0.0, 'temperature 2': row[1]} for row in reader)
Martijn Pieters
fuente
1
¿Por qué los archivos se abren en modo binario? Los archivos csv son, obviamente, texto, no formato binario. Esto podría causar problemas en los sistemas Windows.
pcarter
3
@pcarter: en Python 2, abrir un archivo en modo texto en Windows activa traducciones de nueva línea que son incompatibles con el formato CSV; por lo tanto, el csvmódulo quiere manejar las nuevas líneas directamente (usando \ny \r\nsegún sea necesario), lo que significa que debe abrir el archivo en modo binario. Vea la csv.reader()documentación : Si csvfile es un objeto de archivo, debe abrirse con la bandera 'b' en plataformas donde eso marca la diferencia. . En Python 3, usaría la newline=''opción en su lugar.
Martijn Pieters
Esto funciona, cosa curiosa: cuando el archivo se abre en amodo, writer.writeheader()escribirá el encabezado dos veces a pesar de que la fila del encabezado ya esté escrita.
loretoparisi
2
@loretoparisi: por supuesto que sí. No lo use writer.writeheader()cuando agregue a un archivo existente. El csv.writer()objeto no puede detectar que está escribiendo datos en un archivo existente.
Martijn Pieters
En Python 3, es necesario abrir el archivo con la opción 'w', el binario no funcionará. Sería útil mencionar esto en la respuesta. Encontré esta diferencia aquí: stackoverflow.com/questions/34283178/…
Kristóf
6

Solo agrega una fila adicional antes de ejecutar el ciclo. Esta fila contiene el nombre del encabezado de su archivo CSV.

schema = ['a','b','c','b']
row = 4
generators = ['A','B','C','D']
with open('test.csv','wb') as csvfile:    
     writer = csv.writer(csvfile, delimiter=delimiter)
# Gives the header name row into csv
     writer.writerow([g for g in schema])   
#Data add in csv file       
     for x in xrange(rows):
         writer.writerow([g() for g in generators])
Mitul Panchal
fuente
3

Esto funcionó para mí.

header = ['row1', 'row2', 'row3']
some_list = [1, 2, 3]
with open('test.csv', 'wt', newline ='') as file:
    writer = csv.writer(file, delimiter=',')
    writer.writerow(i for i in header)
    for j in some_list:
        writer.writerow(j)
saggzz
fuente