CSV verilerini işlerken ilk veri satırı nasıl göz ardı edilir?


113

Python'dan bir CSV verisi sütunundan minimum sayıyı yazdırmasını istiyorum, ancak en üst satır sütun numarası ve Python'un en üst satırı hesaba katmasını istemiyorum. Python'un ilk satırı yok saydığından nasıl emin olabilirim?

Şimdiye kadarki kod bu:

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

Sadece kodu vermekle kalmayıp, ne yaptığınızı da açıklayabilir misiniz? Python'da çok yeniyim ve her şeyi anladığımdan emin olmak istiyorum.


5
1.0Dosyanızdaki her satır için bir döndüren ve ardından minimum olanı alan bir jeneratör oluşturduğunuzun farkında mısınız 1.0?
Wooble

@ Wooble Teknik olarak, büyük bir jeneratör 1.0. :)
Dougal

@ Wooble iyi yakaladı - ... datatype(row[column]... sanırım OP'nin başarmaya çalıştığı şey bu
Jon Clements

Birisi bu kodu benim için yazdım ve anlayamadım, yani teşekkürler haha!

Yanıtlar:


106

csvModül Sniffersınıfının bir örneğini, bir CSV dosyasının biçimini çıkarmak ve next()yalnızca gerektiğinde ilk satırı atlamak için yerleşik işlevle birlikte bir başlık satırının mevcut olup olmadığını tespit etmek için kullanabilirsiniz:

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)

Yana datatypeve columnsizin örnekte önceden kodlanmıştır, bu süreç biraz daha hızlı olacaktır rowböyle:

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

Not: Yukarıdaki kod Python 3.x içindir. Python 2.x için, gösterilenler yerine dosyayı açmak için aşağıdaki satırı kullanın:

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

2
Bunun yerine has_header(file.read(1024))yazmak mantıklı has_header(file.readline())mı? Bunu çok görüyorum, ancak has_reader()CSV dosyasının tek bir satırından bir başlık olup olmadığını nasıl tespit edebileceğimi anlamıyorum ...
Anto

1
@Anto: Cevabımdaki kod, dokümantasyondaki "Sniffer kullanımı için örnek" e dayanmaktadır , bu yüzden bunu yapmanın öngörülen yolu olduğunu varsayıyorum. Ben her zaman yeterli veri böyle bir kararlılık-ama yapmak o zamandan beri hiçbir fikrim yok olacak gibi bir veri hattı temelinde yapıyor görünmüyor konusunda hemfikir nasılSniffer çalışır tarif edilmez. FWIW Kullanıldığını hiç görmedim has_header(file.readline())ve çoğu zaman işe yarasa bile, belirtilen nedenlerden ötürü yaklaşımdan oldukça şüphelenirdim.
martineau

Girdiniz için teşekkürler. Yine de kullanımın file.read(1024) python'un csv lib :. dosyasında hatalar oluşturduğu görülüyor . Örneğin buraya da bakın .
Anto

@Anto: Hiç böyle bir hatayla karşılaşmadım - 1024 bayt sonuçta çok fazla bellek değil - ne de bu yanıtın aldığı olumlu oylara (ve binlerce Belgeleri okuyan ve takip eden kişilerin oranı). Bu nedenlerden dolayı, sorununuza başka bir şeyin neden olduğundan kesinlikle şüpheleniyorum.
martineau

Geçiş yaptığım anda aynı hatayla readline()karşılaştım read(1024). Şimdiye kadar sadece csv.dialect sorununu çözmek için readline'a geçen insanları bulmayı başardım.
Anto

75

İlk satırı atlamak için arayın:

next(inf)

Python'daki dosyalar, satırlar üzerinden yineleyicilerdir.


22

Benzer bir kullanım durumunda, gerçek sütun isimlerimin bulunduğu satırın önündeki sinir bozucu satırları atlamak zorunda kaldım. Bu çözüm iyi çalıştı. Önce dosyayı okuyun, ardından listeyi iletin 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)))

Teşekkürler Veedrac. Burada öğrenmekten mutluluk duyuyoruz, alıntı yaptığınız sorunları çözecek düzenlemeler önerebilir misiniz? Çözümüm işi hallediyor, ancak daha da geliştirilebilecek gibi görünüyor?
Maarten

1
Size kodu aynı olması gereken (denenmemiş) bir şeyle değiştiren bir düzenleme verdim. Demek istediğinize uygun değilse, geri dönmekten çekinmeyin. Hala neden datasözlüğü yaptığından emin değilim ve bu cevap kabul edilenin üzerine gerçekten bir şey eklemiyor.
Veedrac

Teşekkürler Veedrac! Bu gerçekten çok verimli görünüyor. Cevabımı gönderdim çünkü kabul edilen cevap benim için çalışmıyordu (nedenini şimdi hatırlayamıyorum). Data = dict () tanımlanması ve ardından hemen doldurulması (önerinize kıyasla) ile ilgili sorun ne olurdu?
Maarten

1
Yapmak ve doldurmak yanlış değil data = dict(), ama verimsiz ve deyimsel değil. Artı, dict literals ( {}) ve enumerateo zaman bile kullanılmalıdır.
Veedrac

1
FWIW, bana @Veedracbildirildiğinden emin olmak için gönderilerime ile cevap vermelisiniz, ancak Stack Overflow kullanıcı adından tahmin edebiliyor gibi görünüyor. ( @Maarten
Cevaplayana

21

Python yemek kitabından ödünç alınmıştır ,
Daha kısa bir şablon kodu şöyle görünebilir:

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

Normalde next(incsv)yineleyiciyi bir satır ilerletecek olanı kullanırsınız , böylece başlığı atlarsınız. Diğeri (30 satır atlamak istediğinizi varsayalım):

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

6

csv.Reader yerine csv.DictReader kullanın. Fieldnames parametresi atlanırsa, csvfile'ın ilk satırındaki değerler alan adları olarak kullanılır. daha sonra ["1"] satırını vb. kullanarak alan değerlerine erişebilirsiniz.


2

Yeni 'pandalar' paketi, 'csv'den daha alakalı olabilir. Aşağıdaki kod, varsayılan olarak ilk satırı sütun başlığı olarak yorumlayarak bir CSV dosyasını okuyacak ve sütunlar arasındaki minimum değeri bulacaktır.

import pandas as pd

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

ve bunu tek satırda da yazabilirsiniz:pd.read_csv('all16.csv').min()
Finn Årup Nielsen

1

Benim mini paket kitaplığım da bu işi yapar.

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

Bu arada, birinci başlık sütun dizininin ne olduğunu biliyorsanız, örneğin "Sütun 1", bunun yerine şunu yapabilirsiniz:

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

1

Benim için gitmenin en kolay yolu menzil kullanmaktır.

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

Bu yaptığım bir şeyle ilgili olduğu için burada paylaşacağım.

Ya bir başlık olup olmadığından emin değilsek ve siz de algılayıcı ve diğer şeyleri içe aktarmak istemiyorsanız?

Göreviniz bir liste veya diziye yazdırma veya ekleme gibi basitse, yalnızca bir if ifadesi kullanabilirsiniz:

# 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 modülü için belgeleri bu örneği sağlamaktadır:

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

SnifferDeneyecektir CSV dosyası hakkında çok şey otomatik olarak algılama. has_header()Dosyanın bir başlık satırı olup olmadığını belirlemek için yöntemini açıkça çağırmanız gerekir . Varsa, CSV satırlarını yinelerken ilk satırı atlayın. Bunu şu şekilde yapabilirsiniz:

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

0

İstenmeyen ilk satırdan kurtulmak için kuyruk kullanırdım :

tail -n +2 $INFIL | whatever_script.py 

0

sadece [1:] ekleyin

aşağıdaki örnek:

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

benim için iPython'da çalışıyor


0

Python 3.X

UTF8 BOM + HEADER'ı işler

csvModülün başlığı kolayca alamaması oldukça sinir bozucuydu, ayrıca UTF-8 BOM (dosyadaki ilk karakter) ile ilgili bir hata var. Bu benim için yalnızca csvmodülü kullanarak çalışıyor :

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'ı listeye dönüştürür, ardından ilk öğeyi açarım

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

Okuyucunun yinelenebilir nesnesinin sonraki satırını, geçerli lehçeye göre çözümlenmiş bir liste olarak döndürür.

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

Okuyucunun yinelenebilir nesnesinin bir sonraki satırını, geçerli lehçeye göre ayrıştırılmış bir liste olarak (nesne reader'dan () döndürülmüşse) veya bir dict (DictReader örneğiyse) olarak döndürür. Genellikle bunu bir sonraki (okuyucu) olarak adlandırmalısınız.

csv_data = csv.reader(open('sample.csv'))
csv_data.__next__() # skip first row
for row in csv_data:
    print(row) # should print second row
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.