一、文件讀取
在Pandas的使用場景中,最多的是將表格型的數據讀取為DataFrame對象。實現這一功能的函數有很多,最常用的是read_csv
和read_table
。
下表列出了pandas主要的讀寫函數:
函數 | 說明 |
d_csv | 讀取默認以逗號作為分隔符的文件 |
read_table | 讀取默認以制表符分隔的文件 |
read_fwf | 從特定寬度格式的文件中讀取數據(無分隔符) |
read_clipboard |
read_table 的剪貼板版本 |
read_excel | 從EXCEL的XLS或者XLSX文件中讀取數據 |
read_hdf | 讀取用pandas存儲的HDF5文件 |
read_html | 從HTML文件中讀取所有表格數據 |
read_json | 從JSON字符串中讀取數據 |
read_msgpack | 讀取MessagePack格式存儲的任意對象 |
read_pickle | 讀取以Python Pickle格式存儲的對象 |
read_sas | 讀取SAS系統中定制存儲格式的數據集 |
read_sql | 將SQL查詢的結果讀取出來 |
read_stata | 讀取stata格式的數據集 |
read_feather | 讀取Feather二進制格式 |
Pandas不但有這么多的讀取函數,每個函數還有大量的可設置參數。比如read_csv到目前就有超過50個參數。這些函數和參數是如此的復雜,很難有人能夠將它們全部記住,所以當你在讀取文件時遇到了困難,請前往官方文檔,那里的一些示例可能對你有幫助。
讓我們來看看一些具體的例子,首先有這么一個文件:
# ex1.csv
a,b,c,d,message 1,2,3,4,hello 5,6,7,8,world 9,10,11,12,foo
可以使用read_csv方法讀取它,默認第一行為列索引,自動生成了行索引:
In [14]: df = pd.read_csv('d:/ex1.csv') In [15]: df Out[15]: a b c d message 0 1 2 3 4 hello 1 5 6 7 8 world 2 9 10 11 12 foo
也可以使用read_table函數,並指定分隔符為逗號:
In [17]: pd.read_table('d:/ex1.csv',sep=',') Out[17]: a b c d message 0 1 2 3 4 hello 1 5 6 7 8 world 2 9 10 11 12 foo
對於不包含表頭行的文件,比如下面的ex2,要么使用默認列名,要么我們指定列名:
1,2,3,4,hello 5,6,7,8,world 9,10,11,12,foo
注意指定列名用的參數名是names,不是columns:
In [18]: pd.read_csv('d:/ex2.csv',header=None) # 使用默認列名
Out[18]: 0 1 2 3 4 0 1 2 3 4 hello 1 5 6 7 8 world 2 9 10 11 12 foo In [19]: pd.read_csv('d:/ex2.csv', names=['a','b','c','d','message']) # 自定義
Out[19]: a b c d message 0 1 2 3 4 hello 1 5 6 7 8 world 2 9 10 11 12 foo
如果你想將上面的message列當作DataFrame的行索引,可以將它傳遞給參數index_col:
# 注意其中的names依然必須包含message字符串,否則會彈出KeyError
In [20]: pd.read_csv('d:/ex2.csv', names=['a','b','c','d','message'],index_col='message') Out[20]: a b c d message hello 1 2 3 4 world 5 6 7 8 foo 9 10 11 12
如果想讀取成分層索引,則需要為index_col參數傳入一個包含列序號或列名的列表:
# csv_mindex.csv key1,key2,value1,value2 one,a,1,2 one,b,3,4 one,c,5,6 one,d,7,8 two,a,9,10 two,b,11,12 two,c,13,14 two,d,15,16
分層索引類似多級索引,后面會介紹。
In [22]: df = pd.read_csv('d:/csv_mindex.csv', index_col=['key1','key2']) In [23]: df Out[23]: value1 value2 key1 key2 one a 1 2 b 3 4 c 5 6 d 7 8 two a 9 10 b 11 12 c 13 14 d 15 16
對於一些更復雜,或者說更不規整的文件,比如分隔符不固定的情況,需要有更多的處理技巧,比如下面這個文件,以不同數量的空格分隔:
# ex3.txt
A B C aaa -0.264438 -1.026059 -0.619500 bbb 0.927272 0.302904 -0.032399 ccc -0.264273 -0.386314 -0.217601 ddd -0.871858 -0.348382 1.100491
這時候需要傳入一個正則表達式作為分隔符參數:
In [25]: result = pd.read_table('d:/ex3.txt', sep='\s+') In [26]: result Out[26]: A B C aaa -0.264438 -1.026059 -0.619500 bbb 0.927272 0.302904 -0.032399 ccc -0.264273 -0.386314 -0.217601 ddd -0.871858 -0.348382 1.100491
上面的正則表達式是\s+
。並且由於列名比數據的列數少一個,系統自動推斷第一列應當作為行索引。
大多數讀取函數都帶有很多幫助我們處理各種異常情況的參數,比如可以使用skiprows來跳過數據中的指定行.
原始數據:
# hey!
a,b,c,d,message # just wanted to make things more difficult for you # who reads CSV files with computers, anyway?
1,2,3,4,hello 5,6,7,8,world 9,10,11,12,foo
我們需要跳過無用的第1、3、4行廢話:
In [27]: pd.read_csv('d:/ex4.csv', skiprows=[0,2,3]) Out[27]: a b c d message 0 1 2 3 4 hello 1 5 6 7 8 world 2 9 10 11 12 foo
缺失值的處理是讀取數據時非常重要的部分。通常情況下,缺失值要么不顯示,直接空着,要么用一些標識值表示,比如NA或NULL。
看下面的數據,注意第三行的6和8之間有個空的:
something,a,b,c,d,message one,1,2,3,4,NA two,5,6,,8,world three,9,10,11,12,foo
read_csv
會將缺失值自動讀成NaN:
In [30]: result = pd.read_csv('d:/ex5.csv') In [31]: result Out[31]: something a b c d message 0 one 1 2 3.0 4 NaN 1 two 5 6 NaN 8 world 2 three 9 10 11.0 12 foo In [32]: pd.isnull(result) Out[32]: something a b c d message 0 False False False False False True 1 False False False True False False 2 False False False False False False
我們可以額外指定na_values
參數,將某些值也當作缺失值來看待,比如下面我們將3.0也當作缺失值對待:
In [40]: result = pd.read_csv('d:/ex5.csv',na_values=[3.0]) In [41]: result Out[41]: something a b c d message 0 one 1 2 NaN 4 NaN 1 two 5 6 NaN 8 world 2 three 9 10 11.0 12 foo
甚至可以對不同的列,指定不同的缺失值標識:
In [42]: f = {'message':['foo','NA'],'something':['two']} In [43]: result = pd.read_csv('d:/ex5.csv',na_values=f) In [44]: result Out[44]: something a b c d message 0 one 1 2 3.0 4 NaN 1 NaN 5 6 NaN 8 world 2 three 9 10 11.0 12 NaN
下表列出了read_csv
和read_table
函數的一些常用參數:
參數 | 說明 |
path | 文件路徑 |
sep | 指定分隔符或正則表達式 |
header | 用作列名的行號 |
index_col | 用作行索引的列名或列號 |
names | 結果的列名列表 |
skiprows | 從起始處,需要跳過的行 |
na_values | 需要用NaN替換的值 |
comment | 在行結尾處分隔注釋的字符 |
parse_dates | 嘗試將數據解析為datetime,默認是False |
keep_date_col |
如果連接列到解析日期上,保留被連接的列,默認False |
converters | 包含列名稱映射到函數的字典 |
dayfirst | 解析非明確日期時,按國際格式處理 |
date_parser | 用於解析日期的函數 |
nrows | 從文件開頭處讀入的行數 |
iterator | 返回一個TextParser對象,用於零散地讀入文件 |
chunksize | 用於迭代的塊大小 |
skip_footer | 忽略文件尾部的行數 |
verbose | 打印各種解析器輸出的信息 |
encoding | 文本編碼,比如UTF-8 |
thousands | 定義千位分隔符,例如逗號或者圓點 |
二、分塊讀取
當我們處理大型文件的時候,讀入文件的一個小片段或者按小塊遍歷文件是比較好的做法。
在這之前,我們最好先對Pandas的顯示設置進行調整,使之更為緊湊:
In [45]: pd.options.display.max_rows = 10
這樣,即使是大文件,最多也只會顯式10行具體內容。
In [46]: result = pd.read_csv('d:/ex6.csv') In [47]: result Out[47]: one two three four key 0 0.467976 -0.038649 -0.295344 -1.824726 L 1 -0.358893 1.404453 0.704965 -0.200638 B 2 -0.501840 0.659254 -0.421691 -0.057688 G 3 0.204886 1.074134 1.388361 -0.982404 R 4 0.354628 -0.133116 0.283763 -0.837063 Q ... ... ... ... ... .. 9995 2.311896 -0.417070 -1.409599 -0.515821 L 9996 -0.479893 -0.650419 0.745152 -0.646038 E 9997 0.523331 0.787112 0.486066 1.093156 K 9998 -0.362559 0.598894 -1.843201 0.887292 G 9999 -0.096376 -1.012999 -0.657431 -0.573315 0 [10000 rows x 5 columns]
或者使用nrows參數,指明從文件開頭往下只讀n行:
In [48]: result = pd.read_csv('d:/ex6.csv',nrows=5) In [49]: result Out[49]: one two three four key 0 0.467976 -0.038649 -0.295344 -1.824726 L 1 -0.358893 1.404453 0.704965 -0.200638 B 2 -0.501840 0.659254 -0.421691 -0.057688 G 3 0.204886 1.074134 1.388361 -0.982404 R 4 0.354628 -0.133116 0.283763 -0.837063 Q
或者指定chunksize作為每一塊的行數,分塊讀入文件:
In [50]: chunker = pd.read_csv('d:/ex6.csv', chunksize=1000) In [51]: chunker Out[51]: <pandas.io.parsers.TextFileReader at 0x2417d6cfb38>
上面的TextFileReader對象是一個可迭代對象。例如我們可以遍歷它,並對‘key’列進行聚合獲得計數值:
In [52]: total = pd.Series([]) In [53]: for piece in chunker: ...: total = total.add(piece['key'].value_counts(), fill_value=0) ...: total = total.sort_values(ascending=False) In [54]: total Out[54]: E 368.0 X 364.0 L 346.0 O 343.0 Q 340.0 ... 5 157.0
2 152.0 0 151.0
9 150.0
1 146.0 Length: 36, dtype: float64 In [55]: total[:10] Out[55]: E 368.0 X 364.0 L 346.0 O 343.0 Q 340.0 M 338.0 J 337.0 F 335.0 K 334.0 H 330.0 dtype: float64