2012-01-25 20 views
28

¿Cuál es la mejor manera de tomar un archivo de datos que contiene una fila de encabezado y leer esta fila en una tupla con nombre para que se pueda acceder a las filas de datos por el nombre del encabezado?¿Cuál es la forma pitónica de leer los datos de archivo CSV como filas de namedtuples?

estaba intentando algo como esto:

import csv 
from collections import namedtuple 

with open('data_file.txt', mode="r") as infile: 
    reader = csv.reader(infile) 
    Data = namedtuple("Data", ", ".join(i for i in reader[0])) 
    next(reader) 
    for row in reader: 
     data = Data(*row) 

El lector de objeto no es subscriptable, por lo que el código anterior arroja un TypeError. ¿Cuál es la forma pitónica de leer un encabezado de archivo en una ruta de acceso nombrada?

Respuesta

31

Uso:

Data = namedtuple("Data", next(reader)) 

y omitir la línea:

next(reader) 

Combinando esto con una versión iterativo basado en el comentario de Martineau continuación, el ejemplo se hace para Python 2

import csv 
from collections import namedtuple 
from itertools import imap 

with open("data_file.txt", mode="rb") as infile: 
    reader = csv.reader(infile) 
    Data = namedtuple("Data", next(reader)) # get names from column headers 
    for data in imap(Data._make, reader): 
     print data.foo 
     # ...further processing of a line... 

y para Python 3

import csv 
from collections import namedtuple 

with open("data_file.txt", newline="") as infile: 
    reader = csv.reader(infile) 
    Data = namedtuple("Data", next(reader)) # get names from column headers 
    for data in map(Data._make, reader): 
     print(data.foo) 
     # ...further processing of a line... 
+1

drbunsen: Después de hacer esto, puede cambiar el procesamiento de bucle : 'para datos en el mapa (Data._make, reader):'. – martineau

+0

@spinup: Cambié tu edición un poco. – martineau

+0

¿Qué sucede si los datos de csv no tienen un encabezado? ¿Hay alguna manera de asignar un nombre a una columna? (Si los datos CSV carece de un encabezado con nombre, y desea asignar nombres de columna, entonces me parece que mi única opción es leerlo como una secuencia de diccionarios). –

20

Por favor, eche un vistazo a csv.DictReader. Básicamente, proporciona la capacidad de obtener los nombres de las columnas de la primera fila como lo está buscando y, después de eso, le permite acceder a cada columna en una fila por nombre usando un diccionario.

Si por alguna razón usted todavía necesita para acceder a las filas como un collections.namedtuple, debería ser fácil de transformar los diccionarios de tuplas nombrados de la siguiente manera:

with open('data_file.txt') as infile: 
    reader = csv.DictReader(infile) 
    Data = collections.namedtuple('Data', reader.fieldnames) 
    tuples = [Data(**row) for row in reader] 
+2

El problema con esta solución es que cada fila se convierte a un diccionario y luego se convierte a la tupla nombrada. Ineficiente si no se requiere el diccionario intermedio. –

+0

Esto no conserva el orden, por lo que la primera columna de su csv se convierte en una aleatoria en su tilde nombrada. En ese momento, también podría usar un dict. – hraban

Cuestiones relacionadas