這是 月小水長(zhǎng) 的第 48 篇原創(chuàng)干貨前面我們學(xué)完了 pandas 中最重要的兩個(gè)數(shù)據(jù)結(jié)構(gòu): Series 和 DataFrame,今天來(lái)侃侃 pandas 讀寫(xiě)文件的那些 tricks,我有十足的信心,大家看了定會(huì)有所收獲。
讀寫(xiě) csv 的正確姿勢(shì)
假如要保存下面這個(gè) DataFrame

保存到 csv 中,我常用的一行代碼是:
df.to_csv('exam_result.csv', index=False, encoding='utf-8-sig')
第一個(gè)參數(shù)是保存的文件名,第二個(gè)參數(shù)是不保存 index 索引,第三個(gè)參數(shù)是指定保存的編碼格式為 utf-8-sig。
基于實(shí)踐是檢驗(yàn)真理的唯一標(biāo)準(zhǔn)原則,先做一組不保存/保存 index 索引列的對(duì)比實(shí)驗(yàn)。

保存 index 的 csv

不保存 index 的 csv
再用 pd.read_csv 分別讀這兩個(gè)文件,如果讀取了沒(méi)有保存了 index 索引的,直接用下面這行代碼即可:
df = pd.read_csv('exam_result.csv')
如果是讀取了保存了 index 索引列的,用上面這句講道理也不會(huì)報(bào)錯(cuò),但是會(huì)多出了一個(gè)'Unnamed:0'
列,稍不注意,就會(huì)對(duì) iloc 等后續(xù)操作造成影響,所以必須去掉這一列,可加一個(gè)參數(shù):
index_col = 0
實(shí)現(xiàn),總結(jié)來(lái)說(shuō),讀寫(xiě) csv,有下面兩種組合方式:
# wirte of way1
df.to_csv('exam_result.csv', index=False, encoding='utf-8-sig')
# read of way1
df = pd.read_csv('exam_result.csv')
# write of way2
df.to_csv('exam_result.csv', encoding='utf-8-sig')
# read of way2
df = pd.read_csv('exam_result.csv', index_col=0)
至于 encoding 這個(gè)參數(shù),為什么取 utf-8-sig 呢?,常見(jiàn)的還有 utf-8,這兩者區(qū)別聯(lián)系何在?
- utf-8 是以字節(jié)為編碼單元,它的字節(jié)順序在所有系統(tǒng)中都是一樣的,沒(méi)有字節(jié)序問(wèn)題,因此它不需要 BOM,所以當(dāng)用 utf-8 編碼方式讀取帶有 BOM 的文件時(shí),它會(huì)把 BOM 當(dāng)做是文件內(nèi)容來(lái)處理, 就會(huì)報(bào)錯(cuò)。
- uft-8-sig 中 sig 全拼為 signature 也就是 帶有簽名的 utf-8,因此 utf-8-sig 讀取帶有 BOM 的 utf-8 文件時(shí)會(huì)把 BOM 單獨(dú)處理,與文本內(nèi)容隔離開(kāi),也是我們期望的結(jié)果。
由于 Windows 下如果設(shè)置為 utf-8,用 Office Excel 打開(kāi)的話會(huì)發(fā)現(xiàn)中文亂碼,因?yàn)?Excel 默認(rèn)這個(gè)文件是有 BOM 的(BOM 是微軟提出的,必然要在自家產(chǎn)品上推廣),實(shí)際上文件沒(méi)有 BOM,一來(lái)二去就亂碼了,使用 utf-8-sig 可以有效避免這個(gè)問(wèn)題。不止 csv 和 excel
常用的都是 read_csv/to_csv/read_excel/to_excel 這四個(gè)來(lái)實(shí)現(xiàn)讀寫(xiě) csv/excel,實(shí)際上常用的還有 json 和 html 兩種形式。json 讀寫(xiě)示例
df.to_json('exam_result.json')
df = pd.read_json('exam_result.json')
exam_result.json 內(nèi)容如下:
實(shí)際上所有的內(nèi)容都在一行,為了方便截圖,我展開(kāi)成了六行;其中 '0','1' 等是 index 而不是下標(biāo),注意區(qū)分。html 讀寫(xiě)示例
df.to_html('exam_result.html')
df = pd.read_html('exam_result.html')
exam_result.html 用瀏覽器打開(kāi)如下:
為什么叫 csv
csv 全稱(chēng) Comma Separated Values,即逗號(hào)分隔值,見(jiàn)名知意,每行各個(gè)字段是以逗號(hào)分隔的。

常見(jiàn)的還有 tsv,即 Tab 制表符分隔,其實(shí),這個(gè)分隔符,我們可以自定義,以 !、&、@ 等字段值中幾乎不會(huì)出現(xiàn)的字符為宜,如果是字母 a、b、c,容易造成混亂。無(wú)論是 csv、tsv 還是 ?sv,都封裝在 read_csv() 函數(shù)中,以 sep 參數(shù)值作為區(qū)分。df.to_csv('exam_result.msv', sep='@', index=False, encoding='utf-8-sig')
df = pd.read_csv('exam_result.msv', sep='@')
msv 后綴是我隨便起的,只要保證讀寫(xiě)文件名相同即可。
讀不太規(guī)范的 csv
一個(gè)不格式太規(guī)范的 csv 舉例如下:
不規(guī)范之處在于內(nèi)容沒(méi)有從表格的左上角開(kāi)始,如果用常用的· df =pd.read_csv('exam_result.csv')
這樣讀,打印的 dataframe 如下:
這個(gè)時(shí)候,參數(shù) skiprows(跳過(guò)前幾行)和 usecols (只取哪些列) 就派上用場(chǎng)了。df = pd.read_csv('exam_result.csv', skiprows=2,usecols=['name','sex','course','grade'])
活學(xué)活用,利用 usecols,還可以解決前面所說(shuō)的讀取保存了 index 的 csv,出現(xiàn)'Unnamed:0'
的問(wèn)題。