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
GrantU
źródło
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.

Martijn Pieters
źródło
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.

dixhom
źródło
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.

Sam Collins
źródło
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.

Stary Łysy Facet
źródło
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ę

protti
źródło
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

Mithilesh Gupta
źródło
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())
Alex Troush
źródło
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)
serpiko
źródło
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
akshaynagpal
źródło
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
Sean
źródło
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
Amir
źródło
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)
Arthur Gatignol
źródło
1

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

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

kevin
źródło
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.

David Martínez
źródło
1
import pandas as pd
data = pd.read_csv('data.csv') 
totalInstances=len(data)
Sadman Sakib
źródło
-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

Ruben Romo
źródło
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