Làm cách nào để bỏ qua dòng dữ liệu đầu tiên khi xử lý dữ liệu CSV?


113

Tôi đang yêu cầu Python in số tối thiểu từ một cột dữ liệu CSV, nhưng hàng trên cùng là số cột và tôi không muốn Python tính đến hàng trên cùng. Làm cách nào để đảm bảo Python bỏ qua dòng đầu tiên?

Đây là mã cho đến nay:

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

Bạn cũng có thể giải thích những gì bạn đang làm, không chỉ cung cấp mã? Tôi rất mới đối với Python và muốn đảm bảo rằng tôi hiểu mọi thứ.


5
Bạn có biết rằng bạn chỉ đang tạo một trình tạo trả về a 1.0cho mỗi dòng trong tệp của bạn và sau đó lấy mức tối thiểu, điều này sẽ xảy ra 1.0?
Wooble vào

@Wooble Về mặt kỹ thuật, đó là một máy phát điện lớn của 1.0. :)
Dougal

@Wooble bắt tốt - ... datatype(row[column]... là những gì tôi đoán OP đang cố gắng đạt được
Jon Clements

Tôi đã có người viết mã đó cho tôi và không hiểu được, vì vậy cảm ơn haha!

Câu trả lời:


106

Bạn có thể sử dụng một phiên bản csvcủa Snifferlớp mô-đun để suy ra định dạng của tệp CSV và phát hiện xem hàng tiêu đề có xuất hiện cùng với next()hàm tích hợp hay không để chỉ bỏ qua hàng đầu tiên khi cần thiết:

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)

datatypecolumnđược mã hóa cứng trong ví dụ của bạn, nên sẽ nhanh hơn một chút để xử lý rownhư sau:

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

Lưu ý: đoạn mã trên dành cho Python 3.x. Đối với Python 2.x, hãy sử dụng dòng sau để mở tệp thay vì những gì được hiển thị:

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

2
Thay vì has_header(file.read(1024)), nó có ý nghĩa để viết has_header(file.readline())? Tôi thấy rằng rất nhiều, nhưng tôi không hiểu làm thế nào has_reader()có thể phát hiện hay không có một tiêu đề từ một dòng duy nhất của các tập tin CSV ...
Anto

1
@Anto: Mã trong câu trả lời của tôi dựa trên "ví dụ cho việc sử dụng Sniffer" trong tài liệu , vì vậy tôi cho rằng đó là cách được quy định để thực hiện. Tôi đồng ý rằng làm việc đó trên cơ sở một dòng dữ liệu không có vẻ như nó sẽ luôn có đủ dữ liệu để đưa ra quyết định-nhưng như vậy tôi không có ý tưởng từ cách các Sniffercông trình không được mô tả. FWIW tôi chưa bao giờ thấy has_header(file.readline())nó được sử dụng và ngay cả khi nó hoạt động trong hầu hết thời gian, tôi sẽ rất nghi ngờ về phương pháp này vì những lý do đã nêu.
martineau

Cảm ơn vì đầu vào của bạn. Tuy nhiên, có vẻ như việc sử dụng file.read(1024) tạo ra lỗi trong csv lib của python :. Xem thêm ở đây chẳng hạn.
Anto

@Anto: Tôi chưa bao giờ gặp phải lỗi như vậy — 1024 byte không phải là quá nhiều bộ nhớ — cũng không phải là vấn đề đối với nhiều người khác dựa trên số phiếu ủng hộ mà câu trả lời này đã nhận được (cũng như hàng nghìn của những người đã đọc và làm theo tài liệu). Vì những lý do đó, tôi thực sự nghi ngờ điều gì đó khác đang gây ra sự cố của bạn.
martineau

Tôi đã gặp chính xác lỗi này ngay khi chuyển từ readline()sang read(1024). Cho đến nay, tôi chỉ tìm được những người đã chuyển sang readline để giải quyết vấn đề csv.dialect.
Anto

75

Để bỏ qua dòng đầu tiên, chỉ cần gọi:

next(inf)

Các tệp trong Python là các trình lặp trên các dòng.


22

Trong một trường hợp sử dụng tương tự, tôi phải bỏ qua các dòng khó chịu trước dòng có tên cột thực của mình. Giải pháp này hoạt động tốt. Đọc tệp trước, sau đó chuyển danh sách vào 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)))

Cảm ơn Veedrac. Rất vui khi học ở đây, bạn có thể đề xuất các chỉnh sửa có thể giải quyết các vấn đề bạn nêu ra không? Giải pháp của tôi đã hoàn thành công việc, nhưng có vẻ như nó có thể được cải thiện hơn nữa?
Maarten

1
Tôi đã cung cấp cho bạn một bản chỉnh sửa thay thế mã bằng một thứ gì đó phải giống hệt (chưa được kiểm tra). Vui lòng hoàn nguyên nếu nó không phù hợp với ý bạn. Tôi vẫn không chắc tại sao bạn lại làm datatừ điển, cũng như câu trả lời này không thực sự bổ sung bất cứ điều gì so với câu trả lời được chấp nhận.
Veedrac

Cảm ơn Veedrac! Điều đó thực sự trông rất hiệu quả. Tôi đã đăng câu trả lời của mình vì câu trả lời được chấp nhận không phù hợp với tôi (không thể nhớ lý do bây giờ). Vấn đề sẽ xảy ra với việc xác định data = dict () và sau đó điền nó ngay lập tức (so với đề xuất của bạn)?
Maarten

1
Không sai khi làm data = dict()và điền nó vào, nhưng nó không hiệu quả và không phải là thành ngữ. Thêm vào đó, người ta nên sử dụng chữ dict ( {}) và enumeratethậm chí sau đó.
Veedrac

1
FWIW, bạn nên trả lời các bài đăng của tôi @Veedracnếu bạn muốn chắc chắn rằng tôi được thông báo, mặc dù Stack Overflow dường như có thể đoán được từ tên người dùng. (Tôi không viết @Maartenvì người trả lời sẽ được thông báo theo mặc định.)
Veedrac

21

Mượn từ sách dạy nấu ăn python ,
Mã mẫu ngắn gọn hơn có thể trông giống như sau:

import csv
with open('stocks.csv') as f:
    f_csv = csv.reader(f) 
    headers = next(f_csv) 
    for row in f_csv:
        # Process row ...

19

Thông thường, bạn sẽ sử dụng next(incsv)cái nào nâng cao trình lặp một hàng, vì vậy bạn bỏ qua tiêu đề. Cái khác (giả sử bạn muốn bỏ qua 30 hàng) sẽ là:

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

6

sử dụng csv.DictReader thay vì csv.Reader. Nếu tham số tên trường bị bỏ qua, các giá trị trong hàng đầu tiên của tệp csvfile sẽ được sử dụng làm tên trường. sau đó bạn có thể truy cập các giá trị trường bằng hàng ["1"], v.v.


2

Gói 'gấu trúc' mới có thể phù hợp hơn 'csv'. Đoạn mã dưới đây sẽ đọc một tệp CSV, theo mặc định, dòng đầu tiên là tiêu đề cột và tìm giá trị tối thiểu trên các cột.

import pandas as pd

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

và bạn có thể viết nó trong một dòng quá:pd.read_csv('all16.csv').min()
Finn Arup Nielsen

1

Vâng, thư viện trình bao bọc mini của tôi cũng sẽ thực hiện công việc.

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

Trong khi đó, nếu bạn biết chỉ mục của cột tiêu đề là gì, chẳng hạn như "Cột 1", bạn có thể thực hiện việc này thay thế:

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

1

Đối với tôi, cách dễ nhất để đi là sử dụng phạm vi.

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

Vì điều này liên quan đến một việc mà tôi đang làm nên tôi sẽ chia sẻ ở đây.

Điều gì sẽ xảy ra nếu chúng tôi không chắc liệu có tiêu đề hay không và bạn cũng không muốn nhập trình đánh giá và những thứ khác?

Nếu tác vụ của bạn là cơ bản, chẳng hạn như in hoặc thêm vào danh sách hoặc mảng, bạn chỉ có thể sử dụng câu lệnh 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

Các tài liệu cho các mô-đun Python 3 CSV cung cấp ví dụ này:

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 ...

Sniffersẽ cố gắng tự động phát hiện nhiều thứ về tệp CSV. Bạn cần gọi has_header()phương thức của nó một cách rõ ràng để xác định xem tệp có dòng tiêu đề hay không. Nếu đúng, hãy bỏ qua hàng đầu tiên khi lặp lại các hàng CSV. Bạn có thể làm như thế này:

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

0

Tôi sẽ sử dụng đuôi để loại bỏ dòng đầu tiên không mong muốn:

tail -n +2 $INFIL | whatever_script.py 

0

chỉ cần thêm [1:]

ví dụ bên dưới:

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

điều đó phù hợp với tôi trong iPython


0

Python 3.X

Xử lý UTF8 BOM + HEADER

Nó khá bực bội khi csvmô-đun không thể dễ dàng lấy được tiêu đề, cũng có một lỗi với UTF-8 BOM (ký tự đầu tiên trong tệp). Điều này phù hợp với tôi khi chỉ sử dụng csvmô-đun:

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

Tôi sẽ chuyển đổi csvreader thành danh sách, sau đó bật phần tử đầu tiên

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()

Trả lại hàng tiếp theo của đối tượng có thể lặp lại của người đọc dưới dạng danh sách, được phân tích cú pháp theo phương ngữ hiện tại.

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__()

Trả về hàng tiếp theo của đối tượng có thể lặp lại của trình đọc dưới dạng danh sách (nếu đối tượng được trả về từ trình đọc ()) hoặc một dict (nếu là đối tượng DictReader), được phân tích cú pháp theo phương ngữ hiện tại. Thông thường bạn nên gọi đây là tiếp theo (người đọc).

csv_data = csv.reader(open('sample.csv'))
csv_data.__next__() # skip first row
for row in csv_data:
    print(row) # should print second row
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.