Policz, ile rekordów jest w CSV Python?


109

Do odczytu pliku CSV używam języka Python (Django Framework). Jak widzisz, wyciągam tylko 2 linie z tego pliku CSV. To, co próbowałem zrobić, to przechowywać w zmiennej całkowitą liczbę wierszy również w pliku CSV.

Jak mogę uzyskać całkowitą liczbę wierszy?

file = object.myfilePath
fileObject = csv.reader(file)
for i in range(2):
    data.append(fileObject.next()) 

Próbowałem:

len(fileObject)
fileObject.length

1
Co to jest file_read? Czy to uchwyt pliku (jak w file_read = open("myfile.txt")?
David Robinson

1
file_read = csv.reader (file) zaktualizowane pytanie powinno mieć teraz sens.
GrantU

Spójrz na to pytanie, aby poznać przemyślenia na ten temat: stackoverflow.com/questions/845058/…
shredding


Przyjęta odpowiedź @ martjin-pieters jest poprawna, ale to pytanie jest źle sformułowane. W swoim pseudokodzie prawie na pewno chcesz policzyć liczbę wierszy, tj. Rekordów - w przeciwieństwie do „Policz ile wierszy znajduje się w pliku CSV”. Ponieważ niektóre zbiory danych CSV mogą zawierać pola, które mogą być wielowierszowe.
Dan Nguyen

Odpowiedzi:


182

Musisz policzyć liczbę wierszy:

row_count = sum(1 for row in fileObject)  # fileObject is your csv.reader

Użycie sum()z wyrażeniem generatora zapewnia efektywny licznik, unikając przechowywania całego pliku w pamięci.

Jeśli na początku przeczytałeś już 2 wiersze, musisz dodać te 2 wiersze do sumy; wiersze, które zostały już odczytane, nie są liczone.


1
Dzięki. To zadziała, ale czy muszę najpierw przeczytać wiersze? To wydaje się hitem?
GrantU

4
Ci mają czytać wiersze; nie ma gwarancji, że wiersze będą miały stały rozmiar, więc jedynym sposobem, aby je policzyć, jest przeczytanie ich wszystkich.
Martijn Pieters

1
@Escachator: na jakiej platformie jesteś? Czy plik zawiera znaki EOF ( CTRL-Z,\x1A )? Jak otworzyłeś plik?
Martijn Pieters

4
@Escachator: Twoja nazwa pliku ma wtedy 53 znaki. Czytnik pobiera iterowalny lub otwarty obiekt pliku, ale nie przyjmuje nazwy pliku.
Martijn Pieters

6
Zwróć uwagę, że jeśli chcesz ponownie wykonać iterację w czytniku (powiedzmy, aby przetworzyć wiersze), musisz zresetować iterator i odtworzyć obiekt czytnika: file.seek(0)wtedyfileObject = csv.reader(file)
KevinTydlacka

68

2018-10-29 EDYCJA

Dziękuję za komentarze.

Przetestowałem kilka rodzajów kodu, aby uzyskać liczbę wierszy w pliku csv pod względem szybkości. Najlepsza metoda jest poniżej.

with open(filename) as f:
    sum(1 for line in f)

Oto testowany kod.

import timeit
import csv
import pandas as pd

filename = './sample_submission.csv'

def talktime(filename, funcname, func):
    print(f"# {funcname}")
    t = timeit.timeit(f'{funcname}("{filename}")', setup=f'from __main__ import {funcname}', number = 100) / 100
    print('Elapsed time : ', t)
    print('n = ', func(filename))
    print('\n')

def sum1forline(filename):
    with open(filename) as f:
        return sum(1 for line in f)
talktime(filename, 'sum1forline', sum1forline)

def lenopenreadlines(filename):
    with open(filename) as f:
        return len(f.readlines())
talktime(filename, 'lenopenreadlines', lenopenreadlines)

def lenpd(filename):
    return len(pd.read_csv(filename)) + 1
talktime(filename, 'lenpd', lenpd)

def csvreaderfor(filename):
    cnt = 0
    with open(filename) as f:
        cr = csv.reader(f)
        for row in cr:
            cnt += 1
    return cnt
talktime(filename, 'csvreaderfor', csvreaderfor)

def openenum(filename):
    cnt = 0
    with open(filename) as f:
        for i, line in enumerate(f,1):
            cnt += 1
    return cnt
talktime(filename, 'openenum', openenum)

Wynik był poniżej.

# sum1forline
Elapsed time :  0.6327946722068599
n =  2528244


# lenopenreadlines
Elapsed time :  0.655304473598555
n =  2528244


# lenpd
Elapsed time :  0.7561274056295324
n =  2528244


# csvreaderfor
Elapsed time :  1.5571560935772661
n =  2528244


# openenum
Elapsed time :  0.773000013928679
n =  2528244

Podsumowując, sum(1 for line in f)jest najszybszy. Ale może nie być znaczącej różnicy w stosunku do len(f.readlines()).

sample_submission.csv ma 30,2 MB i 31 milionów znaków.


Czy powinieneś również zamknąć plik? zaoszczędzić miejsce?
lesolorzanov

1
Dlaczego w podsumowaniu wolisz sum () zamiast len ​​()? Len () jest szybszy w wynikach!
jorijnsmit

Niezła odpowiedź. Jeden dodatek. Chociaż wolniejsze, należy preferować for row in csv_reader:rozwiązanie, gdy CSV ma zawierać prawidłowe cytowane znaki nowej linii zgodnie z rfc4180 . @dixhom jak duży był testowany plik?
Simon Lang

15

Aby to zrobić, potrzebujesz trochę kodu, takiego jak mój przykład tutaj:

file = open("Task1.csv")
numline = len(file.readlines())
print (numline)

Mam nadzieję, że to pomoże wszystkim.


1
Podoba mi się ta krótka odpowiedź, ale jest wolniejsza niż odpowiedź Martijna Pietersa. W przypadku linii 10 mln %time sum(1 for row in open("df_data_raw.csv")) koszt 4,91 s, a %time len(open("df_data_raw.csv").readlines())koszt 14,6 s.
Pengju Zhao

Oryginalny tytuł pytania („Policz ile wierszy jest w pliku CSV Python”) został sformułowany myląco / myląco, ponieważ osoba pytająca chce określić liczbę wierszy / rekordów. Twoja odpowiedź podałaby nieprawidłową liczbę wierszy w dowolnym zbiorze danych, w którym znajdują się pola ze znakami nowej linii
Dan Nguyen

10

Kilka z powyższych sugestii liczy liczbę LINII w pliku csv. Ale niektóre pliki CSV będą zawierać cytowane ciągi, które same zawierają znaki nowej linii. Pliki MS CSV zwykle oddzielają rekordy znakiem \ r \ n, ale używają samego \ n w obrębie cudzysłowów.

W przypadku takiego pliku zliczanie wierszy tekstu (rozdzielonych znakiem nowej linii) w pliku da zbyt duży wynik. Aby uzyskać dokładne zliczanie, musisz użyć csv.reader do odczytania rekordów.


6

Najpierw musisz otworzyć plik za pomocą open

input_file = open("nameOfFile.csv","r+")

Następnie użyj csv.reader, aby otworzyć plik csv

reader_file = csv.reader(input_file)

Na koniec możesz wziąć numer wiersza z instrukcją „len”

value = len(list(reader_file))

Całkowity kod jest następujący:

input_file = open("nameOfFile.csv","r+")
reader_file = csv.reader(input_file)
value = len(list(reader_file))

Pamiętaj, że jeśli chcesz ponownie użyć pliku csv, musisz utworzyć plik input_file.fseek (0), ponieważ gdy używasz listy dla reader_file, czyta cały plik, a wskaźnik w pliku zmienia swoją pozycję


6

row_count = sum(1 for line in open(filename)) pracował dla mnie.

Uwaga: sum(1 for line in csv.reader(filename))wydaje się, że oblicza długość pierwszej linii


Pierwsza to zliczanie wierszy w pliku. Jeśli twój CSV ma podziały linii w ciągach, nie pokaże dokładnych wyników
Danilo Souza Morães

3
numline = len(file_read.readlines())

2
file_readwidocznie csv.reader()obiektu, więc nie ma się readlines()metodę. .readlines()musi utworzyć potencjalnie dużą listę, którą następnie ponownie odrzucasz.
Martijn Pieters

1
Kiedy piszę tę odpowiedź, w temacie nie ma informacji o csv to obiekt czytnika csv.
Alex Troush

3

kiedy tworzysz instancję obiektu csv.reader i wykonujesz iterację całego pliku, możesz uzyskać dostęp do zmiennej instancji o nazwie line_num, podając liczbę wierszy:

import csv
with open('csv_path_file') as f:
    csv_reader = csv.reader(f)
    for row in csv_reader:
        pass
    print(csv_reader.line_num)

2
import csv
count = 0
with open('filename.csv', 'rb') as count_file:
    csv_reader = csv.reader(count_file)
    for row in csv_reader:
        count += 1

print count

2

Użyj „listy”, aby dopasować bardziej działający obiekt.

Możesz wtedy liczyć, przeskakiwać, mutować do woli:

list(fileObject) #list values

len(list(fileObject)) # get length of file lines

list(fileObject)[10:] # skip first 10 lines

2

Działa to dla csv i wszystkich plików zawierających ciągi znaków w systemach operacyjnych opartych na Uniksie:

import os

numOfLines = int(os.popen('wc -l < file.csv').read()[:-1])

W przypadku, gdy plik csv zawiera wiersz pól, możesz odjąć jeden z numOfLinespowyższych:

numOfLines = numOfLines - 1

Jest to bardzo przydatne do integracji ze skryptem Pythona. +1
Vitalis

2

Możesz także użyć klasycznej pętli for:

import pandas as pd
df = pd.read_csv('your_file.csv')

count = 0
for i in df['a_column']:
    count = count + 1

print(count)

1

może chcieć wypróbować coś tak prostego, jak poniżej w wierszu poleceń:

sed -n '$=' filename lub wc -l filename


Co się stanie, jeśli w cudzysłowach są znaki końca linii? To nadal powinno być uważane za część tego samego rekordu. Ta odpowiedź jest błędna
Danilo Souza Morães

1

Myślę, że możemy trochę poprawić najlepszą odpowiedź, używam:

len = sum(1 for _ in reader)

Co więcej, nie powinniśmy zapominać, że kod Pythona nie zawsze ma najlepszą wydajność w projekcie. Na przykład: Jeśli możemy wykonać więcej operacji w tym samym czasie w tym samym zbiorze danych, lepiej zrobić wszystko w tym samym jądrze, zamiast tego zrobić dwie lub więcej pythonowych kostek.



-1

próbować

data = pd.read_csv("data.csv")
data.shape

a na wyjściu można zobaczyć coś takiego jak (aa, bb), gdzie aa to liczba wierszy


Po prostu natknąłem się na rzeczy, wydaje się, że ten komentarz dotyczący kształtu nie jest taki zły i właściwie stosunkowo bardzo szybki: stackoverflow.com/questions/15943769/ ...
dedricF

Och, ale będziesz chciał zrobićdata.shape[0]
dedricF

Ale czy jest stosunkowo szybki w porównaniu z odpowiedzią @ martijnpieters, która używa standardowego uchwytu / iteratora pliku i nie wymaga instalowania i importowania biblioteki pandas?
Dan Nguyen
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.