Bagaimana cara mengabaikan baris pertama data saat memproses data CSV?

113

Saya meminta Python untuk mencetak angka minimum dari kolom data CSV, tetapi baris teratas adalah nomor kolom, dan saya tidak ingin Python memperhitungkan baris atas. Bagaimana saya bisa memastikan Python mengabaikan baris pertama?

Ini kodenya sejauh ini:

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

Bisakah Anda juga menjelaskan apa yang Anda lakukan, tidak hanya memberikan kodenya? Saya sangat baru mengenal Python dan ingin memastikan bahwa saya memahami segalanya.

martineau.dll
sumber
5
Apakah Anda sadar bahwa Anda baru saja membuat generator yang mengembalikan a 1.0untuk setiap baris dalam file Anda dan kemudian mengambil nilai minimum, yang mana yang akan menjadi 1.0?
Wooble
@Wooble Secara teknis, ini adalah penghasil besar 1.0. :)
Dougal
@Wooble tangkapan yang bagus - ... datatype(row[column]... adalah apa yang saya kira OP sedang coba capai
Jon Clements
Saya meminta seseorang menulis kode itu untuk saya dan tidak mengerti, jadi terima kasih haha!

Jawaban:

106

Anda dapat menggunakan instance kelas csvmodul Snifferuntuk menyimpulkan format file CSV dan mendeteksi apakah baris header ada bersama dengan next()fungsi bawaan untuk melewati baris pertama hanya jika diperlukan:

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)

Karena datatypedan di column-hardcode dalam contoh Anda, akan sedikit lebih cepat untuk memproses rowseperti ini:

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

Catatan: kode di atas adalah untuk Python 3.x. Untuk Python 2.x gunakan baris berikut untuk membuka file alih-alih yang ditampilkan:

with open('all16.csv', 'rb') as file:
martineau.dll
sumber
2
Alih-alih has_header(file.read(1024)), apakah masuk akal untuk menulis has_header(file.readline())? Saya sering melihat itu, tetapi saya tidak mengerti bagaimana has_reader()bisa mendeteksi apakah ada header dari satu baris file CSV ...
Anto
1
@Anto: Kode dalam jawaban saya didasarkan pada "contoh untuk penggunaan Sniffer" dalam dokumentasi , jadi saya berasumsi bahwa itu adalah cara yang ditentukan untuk melakukannya. Saya setuju bahwa melakukannya berdasarkan satu baris data sepertinya tidak selalu cukup untuk membuat keputusan seperti itu — tetapi saya tidak tahu karena bagaimanaSniffer karya - karya itu tidak dijelaskan. FWIW Saya belum pernah melihat has_header(file.readline())digunakan dan bahkan jika itu berhasil sebagian besar waktu, saya akan sangat curiga dengan pendekatan tersebut karena alasan yang disebutkan.
martineau
Terima kasih atas masukan Anda. Namun demikian tampaknya penggunaan file.read(1024) menghasilkan kesalahan dalam python's csv lib :. Lihat juga di sini misalnya.
Anto
@Anto: Saya belum pernah menemukan kesalahan seperti itu — 1024 byte bukanlah memori yang banyak — juga tidak menjadi masalah bagi banyak orang lain berdasarkan suara positif yang diterima jawaban ini (serta ribuan orang yang telah membaca dan mengikuti dokumentasi). Karena alasan tersebut, saya sangat curiga ada hal lain yang menyebabkan masalah Anda.
martineau
Saya mengalami kesalahan yang sama persis setelah saya beralih dari readline()ke read(1024). Sejauh ini saya hanya berhasil menemukan orang yang telah beralih ke readline untuk menyelesaikan masalah csv.dialect.
Anto
75

Untuk melewati baris pertama, panggil saja:

next(inf)

File dengan Python adalah iterator di atas baris.

jfs
sumber
22

Dalam kasus penggunaan serupa saya harus melewati baris yang mengganggu sebelum baris dengan nama kolom saya yang sebenarnya. Solusi ini bekerja dengan baik. Baca file terlebih dahulu, lalu teruskan daftarnya ke 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)))
Maarten
sumber
Terima kasih Veedrac. Senang belajar di sini, dapatkah Anda menyarankan pengeditan yang akan menyelesaikan masalah yang Anda kutip? Solusi saya menyelesaikan pekerjaan, tetapi sepertinya itu dapat lebih ditingkatkan?
Maarten
1
Saya memberi Anda suntingan yang menggantikan kode dengan sesuatu yang harus identik (belum teruji). Jangan ragu untuk mengembalikannya jika tidak sesuai dengan yang Anda maksud. Saya masih tidak yakin mengapa Anda membuat datakamus, juga tidak jawaban ini benar-benar menambahkan apa pun selain yang diterima.
Veedrac
Terima kasih Veedrac! Itu memang terlihat sangat efisien. Saya memposting jawaban saya karena jawaban yang diterima tidak berfungsi untuk saya (tidak dapat mengingat alasannya sekarang). Apa masalah dengan mendefinisikan data = dict () dan kemudian segera mengisinya (dibandingkan dengan saran Anda)?
Maarten
1
Tidak salah untuk melakukan data = dict()dan mengisinya, tetapi ini tidak efisien dan tidak idiomatis. Plus, seseorang harus menggunakan dict literals ( {}) dan enumeratebahkan kemudian.
Veedrac
1
FWIW, Anda harus membalas posting saya dengan @Veedracjika Anda ingin memastikan saya diberi tahu, meskipun Stack Overflow tampaknya dapat menebak dari nama penggunanya. (Saya tidak menulis @Maartenkarena penjawab akan diberi tahu secara default.)
Veedrac
21

Dipinjam dari buku masak python ,
Kode templat yang lebih ringkas mungkin terlihat seperti ini:

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

Anda biasanya akan menggunakan next(incsv)yang memajukan iterator satu baris, jadi Anda melewati tajuk. Yang lainnya (katakanlah Anda ingin melewati 30 baris) adalah:

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

gunakan csv.DictReader, bukan csv.Reader. Jika parameter nama bidang dihilangkan, nilai di baris pertama file csv akan digunakan sebagai nama bidang. Anda kemudian dapat mengakses nilai bidang menggunakan baris ["1"] dll

iruvar
sumber
2

Paket 'panda' baru mungkin lebih relevan daripada 'csv'. Kode di bawah ini akan membaca file CSV, secara default mengartikan baris pertama sebagai tajuk kolom dan menemukan nilai minimum di seluruh kolom.

import pandas as pd

data = pd.read_csv('all16.csv')
data.min()
Finn Årup Nielsen
sumber
dan Anda dapat menuliskannya dalam satu baris juga:pd.read_csv('all16.csv').min()
Finn Årup Nielsen
1

Nah, perpustakaan pembungkus mini saya akan melakukan pekerjaan itu juga.

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

Sementara itu, jika Anda mengetahui indeks kolom header satu, misalnya "Kolom 1", Anda dapat melakukan ini sebagai gantinya:

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

Bagi saya cara termudah untuk pergi adalah dengan menggunakan jangkauan.

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])  
Clint Hart
sumber
1

Karena ini terkait dengan sesuatu yang saya lakukan, saya akan share disini.

Bagaimana jika kami tidak yakin jika ada tajuk dan Anda juga tidak ingin mengimpor sniffer dan hal lainnya?

Jika tugas Anda dasar, seperti mencetak atau menambahkan ke daftar atau larik, Anda bisa menggunakan pernyataan 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)
Roy W.
sumber
1

The dokumentasi untuk modul Python 3 CSV memberikan contoh ini:

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

Ini Snifferakan mencoba mendeteksi secara otomatis banyak hal tentang file CSV. Anda perlu memanggil has_header()metodenya secara eksplisit untuk menentukan apakah file tersebut memiliki baris header. Jika ya, lewati baris pertama saat mengulang baris CSV. Anda bisa melakukannya seperti ini:

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

Saya akan menggunakan tail untuk menghilangkan baris pertama yang tidak diinginkan:

tail -n +2 $INFIL | whatever_script.py 
Karel Adams
sumber
0

tambahkan saja [1:]

contoh di bawah ini:

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

yang berfungsi untuk saya di iPython

pikiran penasaran
sumber
0

Python 3.X

Menangani UTF8 BOM + HEADER

Cukup frustasi bahwa csvmodul tidak dapat dengan mudah mendapatkan header, ada juga bug pada UTF-8 BOM (karakter pertama dalam file). Ini berfungsi untuk saya hanya dengan menggunakan csvmodul:

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]
Christophe Roussy
sumber
0

Saya akan mengonversi csvreader ke daftar, lalu memunculkan elemen pertama

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)
Tim John
sumber
0

Python 2.x

csvreader.next()

Kembalikan baris berikutnya dari objek yang dapat dibaca pembaca sebagai daftar, yang diuraikan menurut dialek saat ini.

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

Kembalikan baris berikutnya dari objek iterable pembaca sebagai daftar (jika objek dikembalikan dari reader ()) atau dict (jika itu adalah instance DictReader), yang diurai sesuai dengan dialek saat ini. Biasanya Anda harus menyebutnya sebagai berikutnya (pembaca).

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