1 引言
數據分析、數據挖掘、可視化是Python的眾多強項之一,但無論是這幾項中的哪一項都必須以數據作為基礎,數據通常都存儲在外部文件中,例如txt、csv、excel、數據庫。本篇中,我們來捋一捋Python中那些外部數據文件讀取、寫入的常用方法。
下表是Pandas官方手冊上給出的一張表格,表格描述的是Pandas中對各種數據文件類型的讀、寫函數,你可以直接在官方手冊中找到:
通過閱讀表格,可以發現,Pandas中提供了非常豐富的數據讀寫方法。不過本文只講述文本文件(txt、csv)、excel文件、關系型數據庫(mysql)、非關系型數據庫(mongodb)的讀寫方式。
2 文本文件(txt、csv)
無論是txt文件還是csv文件,在Pandas中都使用read_csv()方法讀取,當然也使用同一個方法寫入到文件,那就是to_csv()方法。
我們先來說說怎么讀取數據。所要讀取的文件名為“data.csv",文件內容用記事本打開后如下所示:

2.1 讀取數據
為了提供更加多樣化、可定制的功能,read_csv()方法定義了參數數十個參數,還好的是大部分參數並不常用,而且絕大多數情況使用默認值就可以,所以只需要記住以下的幾個比較常用的參數就可以了:
(1)filepath_or_buffer:文件所在路徑,可以是一個描述路徑的字符串、pathlib.Path對象、http或ftp的連接,也可以是任何可調用read()方法的對象。這個參數是唯一一個必傳的參數。
>>> import pandas as pd >>> df = pd.read_csv('data.csv', encoding='gbk') >>> df 姓名 語文 數學 英語 0 陳一 89 90 67 1 趙二 70 78 90 2 張三 87 86 79 3 李四 90 69 84 4 王五 78 80 69
(2)encoding :編碼,字符型,通常為'utf-8',如果中文讀取不正常,可以將encoding設為’gbk‘。
在上面打開data.csv文件的例子中,如果不指定encoding='gbk'則會出現下面的異常。當然,你也可以在記事本中通過另存為的方式將編碼修改為utf-8,這樣就可以使用默認的utf-8編碼。
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd0 in position 0: invalid continuation byte
(3)sep:分隔符,默認為一個英文逗號,即','。
(4)delimiter :備選分隔符,如果指定了delimiter則sep失效。
(5)header :整數或者由整數組成的列表,以用來指定由哪一列或者哪幾列作為列名,默認為header=0,表示第一列作為列名。
>>> pd.read_csv('data.csv', encoding='gbk', header=1) # 指定第二列作為列名 陳一 89 90 67 0 趙二 70 78 90 1 張三 87 86 79 2 李四 90 69 84 3 王五 78 80 69
可以看到,當指定第一行之后的數據作為列名時,前面的所有行都會被略過。
也可以傳遞一個包含多個整數的列表給header,這樣每一列就會有多個列名。如果中間某一行沒有指定,那么改行會被略過,例如下面的第三行:
>>> df = pd.read_csv('data.csv', encoding='gbk', header=[0,1,3]) >>> df 姓名 語文 數學 英語 陳一 89 90 67 張三 87 86 79 0 李四 90 69 84 1 王五 78 80 69
當文件中沒有列名一行數據時,可以傳遞header=None,表示不從文件數據中指定行作為列名,這是Pandas會自動生成從零開始的序列作為列名:
>>> df = pd.read_csv('data.csv', encoding='gbk', header=None) >>> df 0 1 2 3 0 姓名 語文 數學 英語 1 陳一 89 90 67 2 趙二 70 78 90 3 張三 87 86 79 4 李四 90 69 84 5 王五 78 80 69
(6)names:一個列表,為數據額外指定列名。
>>> df = pd.read_csv('data.csv', encoding='gbk', names=['第一列', '第二列', '第三列', '第四列']) >>> df 第一列 第二列 第三列 第四列 0 姓名 語文 數學 英語 1 陳一 89 90 67 2 趙二 70 78 90 3 張三 87 86 79 4 李四 90 69 84 5 王五 78 80 69
2.2 寫入數據
to_csv()方法可以將Pandas數據寫入到文本文件中,常用參數如下:
(1)path_or_buf:表示路徑的字符串或者文件句柄。例如,將上面讀取出來的數據寫入到名為data_1.txt文件中:
df.to_csv('data_1.txt')
如果data_1.txt文件不存在,則會新建data_1.txt文件后再寫入,如果本來已存在該文件,則會清空后再寫入,寫入后data_1.txt文件內容如下:
,第一列,第二列,第三列,第四列
0,姓名,語文,數學,英語
1,陳一,89,90,67
2,趙二,70,78,90
3,張三,87,86,79
4,李四,90,69,84
5,王五,78,80,69
可以看到,無論是行索引還是列名和真實數據都寫入到了文件中。
(2)sep:分隔符,默認為因為逗號’,‘。例如指定分隔符為’-‘將之前讀取的數據寫入文件中:
>>> df.to_csv('data_1.txt', sep='*')
寫入后data_1.txt文件內容如下:
*第一列*第二列*第三列*第四列 0*姓名*語文*數學*英語 1*陳一*89*90*67 2*趙二*70*78*90 3*張三*87*86*79 4*李四*90*69*84 5*王五*78*80*69
(3)header:元素為字符串的列表,或布爾型數據。當為列表時表示重新指定列名,當為布爾型時,表示是否寫入列名:
df.to_csv('data_1.txt', header=['第1列', '第2列', '第3列', '第4列'])
寫入數據后文件內容:
,第1列,第2列,第3列,第4列
0,姓名,語文,數學,英語
1,陳一,89,90,67
2,趙二,70,78,90
3,張三,87,86,79
4,李四,90,69,84
5,王五,78,80,69
(4)columns:一個列表,重新指定寫入文件中列的順序。
df.to_csv('data_1.txt', columns=['第四列', '第二列', '第三列', '第一列'])
寫入后文件內容:
,第四列,第二列,第三列,第一列 0,英語,語文,數學,姓名 1,67,89,90,陳一 2,90,70,78,趙二 3,79,87,86,張三 4,84,90,69,李四 5,69,78,80,王五
(5)index_label :字符串或布爾型變量,設置索引列列名:
>>> df.to_csv('data_1.txt', index_label='index')
寫入后文件內容:
index,第一列,第二列,第三列,第四列
0,姓名,語文,數學,英語
1,陳一,89,90,67
2,趙二,70,78,90
3,張三,87,86,79
4,李四,90,69,84
5,王五,78,80,69
>>> df.to_csv('data_1.txt', index_label=False)
第一列,第二列,第三列,第四列
0,姓名,語文,數學,英語
1,陳一,89,90,67
2,趙二,70,78,90
3,張三,87,86,79
4,李四,90,69,84
5,王五,78,80,69
(6)index:布爾型,是否寫入索引列,默認為True
>>> df.to_csv('data_1.txt', index=False, index_label=False)
第一列,第二列,第三列,第四列
姓名,語文,數學,英語
陳一,89,90,67
趙二,70,78,90
張三,87,86,79
李四,90,69,84
王五,78,80,69
(7)encoding:寫入的編碼,默認是utf-8。
>>> df.to_csv('data_1.csv', encoding='gbk')
寫入后文件內容:
,第一列,第二列,第三列,第四列
0,姓名,語文,數學,英語
1,陳一,89,90,67
2,趙二,70,78,90
3,張三,87,86,79
4,李四,90,69,84
5,王五,78,80,69
3 excel文件
在使用pandas讀取excel文件之前,需要先安裝Python讀取excel的依賴包:xlrd,可以使用pip命令從豆瓣源上下載:
pip install -i https://pypi.douban.com/simple xlrd
示例文件名為data.xlsl,里面有兩張sheet,sheet1內容如下:
Sheet2內容如下:
3.1 讀取數據
pandas讀取excel數據通過reade_excel方法,下面通過實例來感受一下read_excel方法的幾個常用參數:
(1)io:需要讀取的文件,可以是文件路徑、文件網址、file-like對象、xlrd workbook對象。這是唯一一個必填的參數。
>>> pd.read_excel('data.xlsx') 姓名 語文 數學 英語 0 陳一 89 90 67 1 趙二 70 78 90 2 張三 87 86 79 3 李四 90 69 84 4 王五 78 80 69
(2)sheet_name :指定需要讀取的Sheet。有一下幾種情況:
-
整型:通過數字索引讀取Sheet,索引從0開始,sheet_name默認參數就是0,表示讀取第一張Sheet。
>>> pd.read_excel('data.xlsx', sheet_name=1) 姓名 語文 數學 英語 0 李白 70 80 90 1 杜浦 70 80 90 2 王安石 70 80 90 3 蘇東坡 70 80 90 4 李清照 70 80 90
-
字符型:通過名稱來讀取Sheet。
>>> pd.read_excel('data.xlsx', sheet_name='Sheet2') 姓名 語文 數學 英語 0 李白 70 80 90 1 杜浦 70 80 90 2 王安石 70 80 90 3 蘇東坡 70 80 90 4 李清照 70 80 90
- 列表:指定多個需要讀取的Sheet,列表的元素可以使索引,也可以是字符串,例如[0, 1, 'Sheet3']表示讀取第一張、第二張和名為Sheet3的3張Sheet,返回的數據是以列表元素為鍵包含數據的DataFrame對象為值的字典。
>>> data = pd.read_excel('data.xlsx', sheet_name=[0, 'Sheet2']) >>> data[0] 姓名 語文 數學 英語 0 陳一 89 90 67 1 趙二 70 78 90 2 張三 87 86 79 3 李四 90 69 84 4 王五 78 80 69 >>> data['Sheet2'] 姓名 語文 數學 英語 0 李白 70 80 90 1 杜浦 70 80 90 2 王安石 70 80 90 3 蘇東坡 70 80 90 4 李清照 70 80 90
- None:表示讀取所有Sheet,返回的是以Sheet名為鍵,包含數據的DataFrame對象為值的字典。
>>> data = pd.read_excel('data.xlsx', sheet_name=None) >>> data['Sheet1'] 姓名 語文 數學 英語 0 陳一 89 90 67 1 趙二 70 78 90 2 張三 87 86 79 3 李四 90 69 84 4 王五 78 80 69 >>> data['Sheet2'] 姓名 語文 數學 英語 0 李白 70 80 90 1 杜浦 70 80 90 2 王安石 70 80 90 3 蘇東坡 70 80 90 4 李清照 70 80 90
(3)header:指定Sheet的表頭,參數可以表示行索引是整型,表示指定哪一行作為表頭,默認值是0,表示以第一行作為表頭。也可以是元素為整型的列表,表示選用多行作為表頭。
>>> pd.read_excel('data.xlsx', sheet_name='Sheet2', header=1) # 整型指定一行作為表頭 李白 70 80 90 0 杜浦 70 80 90 1 王安石 70 80 90 2 蘇東坡 70 80 90 3 李清照 70 80 90 >>> pd.read_excel('data.xlsx', sheet_name='Sheet2', header=[0,2]) # 列表指定多行作為表頭 姓名 語文 數學 英語 杜浦 70 80 90 0 王安石 70 80 90 1 蘇東坡 70 80 90 2 李清照 70 80 90
(4)index_col :指定行標簽,或者說行名。當時一個整數時,表示指定某一行行作為行標簽,當是一個列表(元素都為整型)時,表示指定多列作為行標簽。默認值為None,表示自動生成以0開始的整數作為行標簽。
>>> pd.read_excel('data.xlsx', sheet_name=0, index_col=0) # 指定第一行作為行標簽 語文 數學 英語 姓名 陳一 89 90 67 趙二 70 78 90 張三 87 86 79 李四 90 69 84 王五 78 80 69 >>> pd.read_excel('data.xlsx', sheet_name=0, index_col=[0, 1]) # 指定第一行第二行作為行標簽 數學 英語 姓名 語文 陳一 89 90 67 趙二 70 78 90 張三 87 86 79 李四 90 69 84 王五 78 80 69
(5)usecols:指定需要加載的列,參數有以下幾種情況:
-
默認值None:表示加載所有列
-
單個整數:加載指定一列,但這種方式未來會被取消,加載單行也最好放在列表里。
>>> pd.read_excel('data.xlsx', sheet_name=0, usecols=1) 姓名 語文 0 陳一 89 1 趙二 70 2 張三 87 3 李四 90 4 王五 78
- 元素為整數的列表:加載指定多列。
>>> pd.read_excel('data.xlsx', sheet_name=0, usecols=[0,2,3]) 姓名 數學 英語 0 陳一 90 67 1 趙二 78 90 2 張三 86 79 3 李四 69 84 4 王五 80 69
3.2 寫入數據
將數據寫入excel得通過DataFrame對象內定義的to_excel()方法。在使用to_excel()方法前,也有一個第三方庫需要裝,那就是openpyxl:
pip install -i https://pypi.douban.com/simple openpyxl
to_excel()方法常用參數如下:
(1)excel_writer:必傳參數,指定需要寫入的excel文件,可以使表示路徑的字符串或者ExcelWriter類對象。
(2)sheet_name:指定需要將數據寫入到哪一張工作表,默認值是Sheet1
(3)float_format:指定浮點型數的格式,例如當指定float_format="%%.2f"時,0.1234將會轉為0.12。
(4)na_rep:字符型,寫入數據時用什么代替空值。
>>> import pandas as pd >>> pd.read_excel('data.xlsx') 姓名 語文 數學 英語 0 陳一 89.0 90.0 67.0 1 趙二 NaN 78.0 90.0 2 張三 87.0 NaN 79.0 3 李四 90.0 69.0 NaN 4 王五 78.0 80.0 69.0 >>> df = pd.read_excel('data.xlsx') >>> df.to_excel('data_1.xlsx', na_rep='--')
寫入后文件內容如下所圖示:

(5)header:是否寫入表頭,值可以使布爾型或者元素為字符串的列表,默認為True表示寫入表頭。
>>> df.to_excel('data_1.xlsx', header=['第一列', '第二列', '第三列', '第四列'])
寫入文件內容如下:

(6)index:是否寫入行號,值為布爾型,默認為True,當為False時上面圖中第一列的行號就不會寫入了。
(7)columns:指定需要寫入文件的列,值是元素為整型或字符串的列表。
4 mysql數據庫
在名為test的數據庫中有一張student的表,表結構和數據如下所示:

現在通過pandas來讀取student表數據。在讀取數據之前,先要安裝Python讀取mysql的第三方庫:
pip install -i https://pypi.douban.com/simple pymysql
pandas讀取mysql數據庫時通過pandas中的read_mysql()方法,主要參數如下:
(1)sql:要執行的查詢SQL語句,必傳參數。
(2)conn:數據庫連接,可以使用pymysql創建,必傳參數。
import pandas as pd import pymysql conn = pymysql.connect(host="localhost",user='chb', password='123456', db="test",charset="utf8") sql = 'select * from student' df = pd.read_sql(sql, conn) print(df) conn.close()
輸出結果如下:
id name Chinese Math English
0 1 陳一 67 60 56
1 2 李紅 89 87 67
2 3 張大 76 56 98
3 4 杜軍 95 90 72
5 mongodb數據庫
pandas中並沒有直接讀取mongodb數據庫的方法提供,這是讓我很疑惑的地方,畢竟mongodb也是主流的非關系型數據庫。在開始之前,請安裝好pymongo第三方:
pip install -i https://pypi.douban.com/simple pymongo
既然pandas中沒有直接讀取mongodb數據庫的方法,我們就需要用將數據用pymongo讀取出來:
import pandas as pd import pymongo client = pymongo.MongoClient(host='localhost', port=27017) db = client['eleme'] db.authenticate('chb', '123456', 'admin') collection = db['test'] data = collection.find() for item in data: print(item)
輸出結果如下:
{'_id': 1, 'name': '張三', 'Chinese': 67, 'Math': 89, 'English': 97}
{'_id': 2, 'name': '李四', 'Chinese': 65, 'Math': 49, 'English': 78}
{'_id': 3, 'name': '王五', 'Chinese': 81, 'Math': 63, 'English': 84}
{'_id': 4, 'name': '黃六', 'Chinese': 70, 'Math': 69, 'English': 73}
將上面的數據傳遞給pandas,實例化DataFrame對象即可:
import pandas as pd import pymongo client = pymongo.MongoClient(host='94.191.85.11', port=27017) db = client['eleme'] db.authenticate('chb', 'psd.mo.1123', 'admin') collection = db['test'] data = collection.find() df = pd.DataFrame(list(data)) # 用讀取出來的數據實例化DataFrame print(df)
輸出結果如下:
_id name Chinese Math English
0 1 張三 67 89 97
1 2 李四 65 49 78
2 3 王五 81 63 84
3 4 黃六 70 69 73
