Contar quantas linhas existem em um CSV Python?

109

Estou usando o python (Django Framework) para ler um arquivo CSV. Eu retiro apenas 2 linhas deste CSV, como você pode ver. O que venho tentando fazer é armazenar em uma variável o número total de linhas do CSV também.

Como posso obter o número total de linhas?

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

Eu tentei:

len(fileObject)
fileObject.length
GrantU
fonte
1
O que é file_read? É um identificador de arquivo (como em file_read = open("myfile.txt")?
David Robinson
1
file_read = csv.reader (file) pergunta atualizada deve fazer sentido agora.
GrantU
Dê uma olhada nesta pergunta para ideias sobre esse tópico: stackoverflow.com/questions/845058/…
shredding

Respostas:

181

Você precisa contar o número de linhas:

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

O uso sum()com uma expressão geradora é um contador eficiente, evitando armazenar todo o arquivo na memória.

Se você já leu 2 linhas para começar, então você precisa adicionar essas 2 linhas ao seu total; linhas que já foram lidas não estão sendo contadas.

Martijn Pieters
fonte
1
Obrigado. Isso funcionará, mas eu tenho que ler as linhas primeiro? Isso parece um pouco de sucesso?
GrantU
4
Você tem que ler as linhas; as linhas não têm um tamanho fixo garantido, então a única maneira de contá-las é lendo todas.
Martijn Pieters
1
@Escachator: em qual plataforma você está? Existem caracteres EOF ( CTRL-Z,\x1A ) no arquivo? Como você abriu o arquivo?
Martijn Pieters
4
@Escachator: seu nome de arquivo tem 53 caracteres então. O leitor pega um objeto iterável ou de arquivo aberto, mas não um nome de arquivo.
Martijn Pieters
6
Observe que se você deseja iterar através do leitor novamente (para processar as linhas, digamos), você precisará redefinir o iterador e recriar o objeto do leitor: file.seek(0)entãofileObject = csv.reader(file)
KevinTydlacka
67

EDITAR 29/10/2018

Obrigado pelos comentários.

Testei vários tipos de código para obter o número de linhas em um arquivo csv em termos de velocidade. O melhor método está abaixo.

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

Aqui está o código testado.

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)

O resultado ficou abaixo.

# 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

Em conclusão, sum(1 for line in f)é o mais rápido. Mas pode não haver diferença significativa de len(f.readlines()).

sample_submission.csv tem 30,2 MB e 31 milhões de caracteres.

Dixhom
fonte
Você também deve fechar o arquivo? economizar espaço?
lesolorzanov
1
Por que você prefere sum () ao invés de len () em sua conclusão? Len () é mais rápido em seus resultados!
jorijnsmit
Boa resposta. Uma adição. Embora mais lento, deve-se preferir a for row in csv_reader:solução quando o CSV deve conter novas linhas entre aspas válidas de acordo com rfc4180 . @dixhom qual era o tamanho do arquivo que você testou?
Simon Lang
16

Para fazer isso, você precisa ter um pouco de código como meu exemplo aqui:

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

Eu espero que isso ajude a todos.

Sam Collins
fonte
1
Gosto desta resposta curta, mas é mais lenta do que a de Martijn Pieters. Para linhas de 10 milhões, %time sum(1 for row in open("df_data_raw.csv")) custa 4,91s enquanto %time len(open("df_data_raw.csv").readlines())custa 14,6s.
Pengju Zhao
10

Várias das sugestões acima contam o número de LINHAS no arquivo csv. Mas alguns arquivos CSV conterão strings entre aspas, que por sua vez contêm caracteres de nova linha. Os arquivos MS CSV geralmente delimitam os registros com \ r \ n, mas usam \ n sozinho nas strings entre aspas.

Para um arquivo como este, contar linhas de texto (conforme delimitado por nova linha) no arquivo dará um resultado muito grande. Portanto, para uma contagem precisa, você precisa usar csv.reader para ler os registros.

Velho careca
fonte
6

Primeiro você tem que abrir o arquivo com

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

Em seguida, use o csv.reader para abrir o csv

reader_file = csv.reader(input_file)

Por último, você pode pegar o número de linhas com a instrução 'len'

value = len(list(reader_file))

O código total é este:

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

Lembre-se que se você quiser reutilizar o arquivo csv, você deve fazer um input_file.fseek (0), porque quando você usa uma lista para o reader_file, ele lê todos os arquivos, e o ponteiro no arquivo muda sua posição

protti
fonte
6

row_count = sum(1 for line in open(filename)) trabalhou para mim.

Nota: sum(1 for line in csv.reader(filename))parece calcular o comprimento da primeira linha

Mithilesh Gupta
fonte
O primeiro é contar o número de linhas em um arquivo. Se o seu csv tiver quebras de linha nas strings, não mostrará resultados precisos
Danilo Souza Morães
3
numline = len(file_read.readlines())
Alex Troush
fonte
2
file_readé aparentemente um csv.reader()objeto, portanto, não tem um readlines()método. .readlines()tem que criar uma lista potencialmente grande, que você então descarta novamente.
Martijn Pieters
1
Quando escrevo esta resposta, o tópico não tem informações sobre csv é o objeto leitor de csv.
Alex Troush
3

ao instanciar um objeto csv.reader e iterar o arquivo inteiro, você pode acessar uma variável de instância chamada line_num fornecendo a contagem de linhas:

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
fonte
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
fonte
2

Use "lista" para ajustar um objeto mais funcional.

Você pode então contar, pular, mudar até o desejo do seu coração:

list(fileObject) #list values

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

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

Isso funciona para csv e todos os arquivos contendo strings em sistemas operacionais baseados em Unix:

import os

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

Caso o arquivo csv contenha uma linha de campos, você pode deduzir um do numOfLinesacima:

numOfLines = numOfLines - 1
Amir
fonte
Isso é muito útil para integração em um script Python. +1
Vitalis
2

Você também pode usar um loop for clássico:

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
fonte
1

pode querer tentar algo tão simples como abaixo na linha de comando:

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

kevin
fonte
E se você tiver quebras de linha entre aspas duplas? Isso ainda deve ser considerado parte do mesmo registro. Resposta errada
Danilo Souza Morães
1

Acho que podemos melhorar um pouco a melhor resposta, estou usando:

len = sum(1 for _ in reader)

Além disso, não devemos esquecer que o código pythônico nem sempre tem o melhor desempenho no projeto. Por exemplo: Se pudermos fazer mais operações ao mesmo tempo no mesmo conjunto de dados, é melhor fazer todas no mesmo bucle, em vez de fazer dois ou mais bucles pitônicos.

David Martínez
fonte
1
import pandas as pd
data = pd.read_csv('data.csv') 
totalInstances=len(data)
Sadman Sakib
fonte
0

experimentar

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

e na saída você pode ver algo como (aa, bb) onde aa é o número de linhas

Ruben Romo
fonte
Apenas tropeçando em coisas, parece que este comentário de forma não é tão ruim e, na verdade, comparativamente muito rápido: stackoverflow.com/questions/15943769/…
dedricF
Oh, mas você vai querer fazer umdata.shape[0]
dedricF