Как питонный способ считывать данные файла CSV в виде строк именованных кортежей? - PullRequest
31 голосов
/ 25 января 2012

Каков наилучший способ взять файл данных, который содержит строку заголовка, и прочитать эту строку в именованный кортеж, чтобы к строкам данных можно было получить доступ по имени заголовка?

Я пытался что-то подобное:

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)

Объект чтения не является подписчиком, поэтому приведенный выше код выдает TypeError.Как питонный способ чтения заголовка файла в именованный кортеж?

Ответы [ 2 ]

37 голосов
/ 25 января 2012

Используйте:

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

и пропустите строку:

next(reader)

Объединяя это с итерационной версией, основанной на комментарии Мартино, приведенном ниже, пример становится для 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...

и для 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...
22 голосов
/ 25 января 2012

Пожалуйста, посмотрите на csv.DictReader. По сути, он предоставляет возможность получать имена столбцов из первой строки в том виде, в каком вы ищете, и после этого позволяет вам получить доступ к каждому столбцу строки по имени, используя словарь.

Если по какой-то причине вам все еще нужно получить доступ к строкам как collections.namedtuple, должно быть легко преобразовать словари в именованные кортежи следующим образом:

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