2017-04-10 68 views
1

如何計算行我有一個像下面在多個CSV文件

文件1

A B 
1 2 
3 4 

文件2

A B 
1 2 

文件3

A B 
1 2 
3 4 
5 6 

我想算csv文件所有csv文件中的行都是

我試圖

f=pd.read_csv(file1)

f.shape

,但是當我有很多的CSV文件的,它需要太多的時間。

我希望得到這樣的結果如下

 rows 
file1 2 
file2 1 
file3 3 

我怎樣才能得到這樣的結果?

回答

5

您可以創建的所有文件的lengthdict然後Series米爲DataFrame添加to_frame

import glob 
import pandas as pd 

files = glob.glob('files/*.csv') 

d = {f: sum(1 for line in open(f)) for f in files} 

print (pd.Series(d)) 

print (pd.Series(d).rename('rows').rename_axis('filename').reset_index()) 

open不保證文件被正確關閉,那麼另一種解決方案:

def file_len(fname): 
    with open(fname) as f: 
     for i, l in enumerate(f): 
      pass 
    return i + 1 

d = {f: file_len(f) for f in files} 
+0

在列表理解中最好使用for循環而不是'open' :) – Roelant

+0

@Claudio - 當然,我也刪除它們。 – jezrael

1

試試這個,

它添加了每個條目fil Ë名稱和節數行和列有適當的標籤:

import os  
df = pd.DataFrame(columns=('file_name', 'rows')) 
for index,i in enumerate(os.listdir('.')): 
    df.loc[index] = [i,len(pd.read_csv(i).index)] 
1

到目前爲止提供的解決方案有非常大的CSV的工作時,是不是最快的。另外,在列表理解中使用open()並不保證文件被正確關閉,例如,當使用with時(見this question)。 所以結合,與見解從this question速度:

from itertools import takewhile, repeat 

def rawincount(filename): 
    with open(filename, 'rb') as f: 
     bufgen = takewhile(lambda x: x, (f.raw.read(1024*1024) for _ in repeat(None))) 
     return sum(buf.count(b'\n') for buf in bufgen) 

和運用由@jezrael提供的解決方案:

import glob 
import pandas as pd 

files = glob.glob('files/*.csv') 
d = {f: rawincount(f) for f in files} 
df = pd.Series(d).to_frame('rows') 
+0

它有兩個問題:#1:它不返回文件中的行數(計數'\ n's不這樣做)#2:速度並不是問題。在我的測試中:4.7秒。對於問題中使用的方法,3.8秒。爲你的功能和4.3秒。在枚舉(f):pass'中使用'for i,l時。無論如何,我很高興你在這裏提供這個。順便說一下:'mapcount'方法(在你提供的鏈接中)提供2.7秒。在我的盒子(Python 3.6,Linux Mint 18.1) – Claudio

+0

:)感謝您的檢查。在Linux中,我會懷疑用'wc -l'調用子進程會不會更快。 – Roelant

2

爲了完整起見,作爲一種所有的摘要說了什麼關於文件速度和適當的打開/關閉這裏一個解決方案,快速工作,不需要太多花哨的代碼,...限於* nix系統(?)(但我認爲類似的技術也可以用於其他系統)。

下面的代碼運行一點點快於rawincount()和計數也不以線的末端有一個「\ n」最後幾行(問題rawincount()有):

import glob, subprocess, pandas 
files = glob.glob('files/*.csv') 
d = {f: subprocess.getoutput("sed -n '$=' " + f) for f in files} 
print(pandas.Series(d)) 

附:在這裏我運行了一些大型文本文件(39個文件總大小爲3.7 GByte,Linux Mint 18.1,Python 3.6)。有趣的是這裏所提出的wc -l *.csv方法的時機:

Results of TIMING functions for getting number of lines in a file: 
    ----------------------------------------------------------------- 
      getNoOfLinesInFileUsing_bash_wc : 1.04 !!! doesn't count last non empty line 
      getNoOfLinesInFileUsing_bash_grep : 1.59 
    getNoOfLinesInFileUsing_mmapWhileReadline : 2.75 
      getNoOfLinesInFileUsing_bash_sed : 3.42 
getNoOfLinesInFileUsing_bytearrayCountLF_B : 3.90 !!! doesn't count last non empty line 
      getNoOfLinesInFileUsing_enumerate : 4.37 
     getNoOfLinesInFileUsing_forLineInFile : 4.49 
    getNoOfLinesInFileUsing_sum1ForLineInFile : 4.82  
getNoOfLinesInFileUsing_bytearrayCountLF_A : 5.30 !!! doesn't count last non empty line 
    getNoOfLinesInFileUsing_lenListFileObj : 6.02 
      getNoOfLinesInFileUsing_bash_awk : 8.61 
1

在* nix系統,如果你能做到這一點的Python之外:

wc -l *.csv 

應該做的伎倆。

+0

'subprocess.getoutput(「wc -l」+ fileName).split()[0]'大約比'sed -n'$ ='「'快三倍,但是......不會計算最後一行文件,如果最後一行不以LF結尾(換行)... – Claudio

+1

你知道如何從文件中提取最後一個字符,也就是FAST,這樣就可以從wc中獲得正確的行數 - 如果最後一個字符不是LF,則加1;? – Claudio

+0

一行的POSIX定義是「零個或多個非零字符加上終止的字符的序列」。沒有立即數想法如何有效地對待不以換行符終止的文件... – efajardo