Як ігнорувати перший рядок даних при обробці даних CSV?


113

Я прошу Python надрукувати мінімальну кількість з стовпця даних CSV, але верхній рядок - це номер стовпця, і я не хочу, щоб Python враховував верхній рядок. Як я можу переконатися, що Python ігнорує перший рядок?

Це код поки що:

import csv

with open('all16.csv', 'rb') as inf:
    incsv = csv.reader(inf)
    column = 1                
    datatype = float          
    data = (datatype(column) for row in incsv)   
    least_value = min(data)

print least_value

Чи можете ви також пояснити, що ви робите, а не просто дати код? Я дуже новачок у Python і хотів би переконатися, що я все розумію.


5
Чи знаєте ви, що ви просто створюєте генератор, який повертає a 1.0для кожного рядка у вашому файлі, а потім приймає мінімум, який буде 1.0?
Wooble

@Wooble Технічно це великий генератор 1.0. :)
Дугал

@ Wooble хороший улов - ... datatype(row[column]... це, напевно, ОП намагається досягти, хоча
Джон Клементс

я мав хтось написати цей код для мене і не зловити це, так що дякую ха-ха!

Відповіді:


106

Ви можете використовувати екземпляр класу csvмодуля Snifferдля виведення формату файлу CSV та виявлення наявності рядка заголовка разом із вбудованою next()функцією, щоб пропускати через перший рядок лише за необхідності:

import csv

with open('all16.csv', 'r', newline='') as file:
    has_header = csv.Sniffer().has_header(file.read(1024))
    file.seek(0)  # Rewind.
    reader = csv.reader(file)
    if has_header:
        next(reader)  # Skip header row.
    column = 1
    datatype = float
    data = (datatype(row[column]) for row in reader)
    least_value = min(data)

print(least_value)

Так datatypeі columnжорстко закодовані в вашому прикладі, це буде трохи швидше обробити rowтак:

    data = (float(row[1]) for row in reader)

Примітка: наведений вище код призначений для Python 3.x. Для Python 2.x використовуйте наступний рядок, щоб відкрити файл замість показаного:

with open('all16.csv', 'rb') as file:

2
Замість того has_header(file.read(1024)), чи є сенс писати has_header(file.readline())? Я бачу це багато, але я не розумію, як has_reader()можна було б визначити, чи є заголовок з одного рядка файлу CSV ...
Анто,

1
@Anto: Код у моїй відповіді базується на "прикладі використання Sniffer" в документації , тому я припускаю, що це встановлений спосіб це зробити. Я згоден , що робить це на основі однієї лінії даних не здається , що він завжди буде достатньо даних , щоб зробити таке визначення, але я поняття не маю , оскільки , як ці Snifferроботи не описує. FWIW Я ніколи не бачив, щоб has_header(file.readline())його використовували, і навіть якби він працював більшу частину часу, я був би дуже підозрілий у підході з вказаних причин.
мартино

Дякуємо за ваш внесок Тим не менш, здається, що використання file.read(1024) генерує помилки в csv lib python :. Дивіться також, наприклад, тут .
Анто

@Anto: Я ніколи не стикався з такою помилкою - 1024 байти все-таки не багато пам’яті, - а також для багатьох інших людей це не було проблемою, грунтуючись на отриманих вище відповідях (як і тисячах) людей, які читали та стежили за документацією). З цих причин я сильно підозрюю, що щось інше спричиняє вашу проблему.
мартіно

Я зіткнувся з цим точно такий же помилкою , як тільки я перейшов від readline()до read(1024). Поки мені вдалося лише знайти людей, які перейшли на читальну лінію, щоб вирішити проблему csv.dialect.
Анто

75

Щоб пропустити перший рядок, просто зателефонуйте:

next(inf)

Файли в Python є ітераторами по рядках.


22

У подібному випадку використання мені довелося пропустити дратівливі рядки перед рядком з моїми власними назвами стовпців. Це рішення спрацювало чудово. Спочатку прочитайте файл, а потім передайте список csv.DictReader.

with open('all16.csv') as tmp:
    # Skip first line (if any)
    next(tmp, None)

    # {line_num: row}
    data = dict(enumerate(csv.DictReader(tmp)))

Дякую Веедраку. Рада дізнатися тут, чи можете ви запропонувати зміни, які вирішили б проблеми, які ви цитуєте? Моє рішення виконує роботу, але, схоже, її можна було б вдосконалити?
Маартен

1
Я дав вам редагування, яке замінює код чимось, що має бути ідентичним (неперевіреним). Сміливо повертайтеся, якщо це не відповідає тому, що ви маєте на увазі. Я досі не впевнений, чому ви складаєте dataсловник, і ця відповідь насправді нічого не додає над прийнятим.
Ведрак

Дякую Веедраку! Це дійсно виглядає дуже ефективно. Я опублікував свою відповідь, оскільки прийнятий не працював для мене (зараз не можу пригадати причину). Яка буде проблема з визначенням даних = dict (), а потім негайно їх заповненням (порівняно з вашою пропозицією)?
Маартен

1
Це неправильно робити data = dict()і заповнювати, але це неефективно і не ідіоматично. Плюс до цього, слід використовувати буквари dict ( {}) і enumerateнавіть тоді.
Ведрак

1
FWIW, ви повинні відповісти на мої повідомлення, @Veedracякщо ви хочете бути впевнені, що я отриманий сповіщенням, хоча, як переповнюється стек, здається, ви зможете здогадатися з імені користувача. (Я не пишу, @Maartenоскільки відповідь буде повідомлений за замовчуванням.)
Ведрак


19

Ви зазвичай використовуєте, next(incsv)який просуває ітератор на один рядок, тому ви пропускаєте заголовок. Іншим (скажімо, ви хочете пропустити 30 рядів) буде:

from itertools import islice
for row in islice(incsv, 30, None):
    # process

6

використовуйте csv.DictReader замість csv.Reader. Якщо параметр імен полів опущений, значення в першому рядку csvfile будуть використовуватися як імена полів. Ви зможете отримати доступ до значень поля за допомогою рядка ["1"] тощо


2

Новий пакет "pandas" може бути більш релевантним, ніж "csv". Код нижче буде читати файл CSV, за замовчуванням інтерпретуючи перший рядок як заголовок стовпця та знаходячи мінімум у стовпцях.

import pandas as pd

data = pd.read_csv('all16.csv')
data.min()

і ви можете написати це також одним рядком:pd.read_csv('all16.csv').min()
Фін Еруп Нільсен

1

Ну, і моя міні-бібліотека для обгортки також зробила б свою роботу.

>>> import pyexcel as pe
>>> data = pe.load('all16.csv', name_columns_by_row=0)
>>> min(data.column[1])

Тим часом, якщо ви знаєте, що таке індекс стовпця заголовка, наприклад, "Стовпець 1", ви можете зробити це замість цього:

>>> min(data.column["Column 1"])

1

Для мене найпростіший шлях - використовувати дальність.

import csv

with open('files/filename.csv') as I:
    reader = csv.reader(I)
    fulllist = list(reader)

# Starting with data skipping header
for item in range(1, len(fulllist)): 
    # Print each row using "item" as the index value
    print (fulllist[item])  

1

Оскільки це пов’язано з чимось, що я робив, я поділюсь тут.

Що робити, якщо ми не впевнені, чи є заголовок, і вам також не здається імпортувати sniffer та інші речі?

Якщо ваше завдання є основним, наприклад, друком або додаванням до списку чи масиву, ви можете просто використовувати оператор if:

# Let's say there's 4 columns
with open('file.csv') as csvfile:
     csvreader = csv.reader(csvfile)
# read first line
     first_line = next(csvreader)
# My headers were just text. You can use any suitable conditional here
     if len(first_line) == 4:
          array.append(first_line)
# Now we'll just iterate over everything else as usual:
     for row in csvreader:
          array.append(row)

1

Документація для модуля Python 3 CSV надає цей приклад:

with open('example.csv', newline='') as csvfile:
    dialect = csv.Sniffer().sniff(csvfile.read(1024))
    csvfile.seek(0)
    reader = csv.reader(csvfile, dialect)
    # ... process CSV file contents here ...

SnifferСпробує автоматично визначити багато про фото CSV. Вам потрібно чітко викликати його has_header()метод, щоб визначити, чи має у файлі рядок заголовка. Якщо так, то пропустіть перший рядок під час ітерації рядків CSV. Ви можете зробити це так:

if sniffer.has_header():
    for header_row in reader:
        break
for data_row in reader:
    # do something with the row

0

Я б використовував хвіст, щоб позбутися від небажаного першого рядка:

tail -n +2 $INFIL | whatever_script.py 

0

просто додайте [1:]

приклад нижче:

data = pd.read_csv("/Users/xyz/Desktop/xyxData/xyz.csv", sep=',', header=None)**[1:]**

що працює для мене в iPython


0

Python 3.X

Ручки UTF8 BOM + HEADER

Було дуже неприємно, що csvмодуль не міг легко отримати заголовок, також є помилка з UTF-8 BOM (перша таблиця у файлі). Для мене це працює лише за допомогою csvмодуля:

import csv

def read_csv(self, csv_path, delimiter):
    with open(csv_path, newline='', encoding='utf-8') as f:
        # https://bugs.python.org/issue7185
        # Remove UTF8 BOM.
        txt = f.read()[1:]

    # Remove header line.
    header = txt.splitlines()[:1]
    lines = txt.splitlines()[1:]

    # Convert to list.
    csv_rows = list(csv.reader(lines, delimiter=delimiter))

    for row in csv_rows:
        value = row[INDEX_HERE]

0

Я б перетворив csvreader у список, а потім вивів перший елемент

import csv        

with open(fileName, 'r') as csvfile:
        csvreader = csv.reader(csvfile)
        data = list(csvreader)               # Convert to list
        data.pop(0)                          # Removes the first row

        for row in data:
            print(row)

0

Python 2.x

csvreader.next()

Поверніть наступний рядок ітерабельного об'єкта читача у вигляді списку, проаналізованого відповідно до поточного діалекту.

csv_data = csv.reader(open('sample.csv'))
csv_data.next() # skip first row
for row in csv_data:
    print(row) # should print second row

Python 3.x

csvreader.__next__()

Повертайте наступний рядок ітерабельного об'єкта читача у вигляді списку (якщо об’єкт повернуто з читача ()) або диктату (якщо це екземпляр DictReader), розібраного відповідно до поточного діалекту. Зазвичай ви повинні викликати це як наступний (читач).

csv_data = csv.reader(open('sample.csv'))
csv_data.__next__() # skip first row
for row in csv_data:
    print(row) # should print second row
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.