【Python基礎】如何用Pandas處理文本數據?

2021-02-13 機器學習初學者

作者:耿遠昊,Datawhale成員,華東師範大學

文本數據是指不能參與算術運算的任何字符,也稱為字符型數據。如英文字母、漢字、不作為數值使用的數字(以單引號開頭)和其他可輸入的字符。

文本數據具有數據維度高、數據量大且語義複雜等特點,是一種較為複雜的數據類型。今天,我們就來一起看看如何使用Pandas對文本數據進行數據處理。

本文目錄

    1. string類型的性質

        1.1. string與object的區別

        1.2. string類型的轉換

    2. 拆分與拼接

        2.1. str.split方法

        2.2. str.cat方法

    3. 替換

        3.1. str.replace的常見用法

        3.2. 子組與函數替換

        3.3. 關於str.replace的注意事項

    4. 字串匹配與提取

        4.1. str.extract方法

        4.2. str.extractall方法

        4.3. str.contains和str.match

    5. 常用字符串方法

        5.1. 過濾型方法

        5.2. isnumeric方法

    6. 問題及練習

        6.1. 問題

        6.2. 練習

一、string類型的性質
1. 1 string與object的區別string類型和object不同之處有三點:① 字符存取方法(string accessor methods,如str.count)會返回相應數據的Nullable類型,而object會隨缺失值的存在而改變返回類型;② 某些Series方法不能在string上使用,例如:Series.str.decode(),因為存儲的是字符串而不是字節;③ string類型在缺失值存儲或運算時,類型會廣播為pd.NA,而不是浮點型np.nan其餘全部內容在當前版本下完全一致,但迎合Pandas的發展模式,我們仍然全部用string來操作字符串。1.2 string類型的轉換

首先,導入需要使用的包

import pandas as pdimport numpy as np

如果將一個其他類型的容器直接轉換string類型可能會出錯:
#pd.Series([1,'1.']).astype('string') #pd.Series([1,2]).astype('string') #pd.Series([True,False]).astype('string') 

當下正確的方法是分兩部轉換,先轉為str型object,在轉為string類型:
pd.Series([1,'1.']).astype('str').astype('string')

0 1
1 1
dtype: string

pd.Series([1,2]).astype('str').astype('string')

0 1
1 2
dtype: string

pd.Series([True,False]).astype('str').astype('string')

0 True
1 False
dtype: string

二、拆分與拼接2.1 str.split方法(a)分割符與str的位置元素選取
s = pd.Series(['a_b_c', 'c_d_e', np.nan, 'f_g_h'], dtype="string")s

0 a_b_c
1 c_d_e
2 <NA>
3 f_g_h
dtype: string

根據某一個元素分割,默認為空格

0 [a, b, c]
1 [c, d, e]
2 <NA>
3 [f, g, h]
dtype: object

這裡需要注意split後的類型是object,因為現在Series中的元素已經不是string,而包含了list,且string類型只能含有字符串。對於str方法可以進行元素的選擇,如果該單元格元素是列表,那麼str[i]表示取出第i個元素,如果是單個元素,則先把元素轉為列表在取出。

0 b
1 d
2 <NA>
3 g
dtype: object

pd.Series(['a_b_c', ['a','b','c']], dtype="object").str[1] #第一個元素先轉為['a','_','b','_','c']

0 _
1 b
dtype: object

(b)其他參數expand參數控制了是否將列拆開,n參數代表最多分割多少次
s.str.split('_',expand=True)

0 [a, b_c]
1 [c, d_e]
2 <NA>
3 [f, g_h]
dtype: object

s.str.split('_',expand=True,n=1)

2.2 str.cat方法

(a)不同對象的拼接模式cat方法對於不同對象的作用結果並不相同,其中的對象包括:單列、雙列、多列① 對於單個Series而言,就是指所有的元素進行字符合併為一個字符串
s = pd.Series(['ab',None,'d'],dtype='string')s

0 ab
1 <NA>
2 d
dtype: string

'abd'

其中可選sep分隔符參數,和缺失值替代字符na_rep參數

'ab,d'

s.str.cat(sep=',',na_rep='*')

'ab,*,d'

② 對於兩個Series合併而言,是對應索引的元素進行合併
s2 = pd.Series(['24',None,None],dtype='string')s2

0 24
1 <NA>
2 <NA>
dtype: string

0 ab24
1 <NA>
2 <NA>
dtype: string

同樣也有相應參數,需要注意的是兩個缺失值會被同時替換
s.str.cat(s2,sep=',',na_rep='*')

0 ab,24
1 *,*
2 d,*
dtype: string

③ 多列拼接可以分為表的拼接和多Series拼接

s.str.cat(pd.DataFrame({0:['1','3','5'],1:['5','b',None]},dtype='string'),na_rep='*')

0 ab15
1 *3b
2 d5*
dtype: string

0 abab0abab
1 <NA>
2 dd0dd
dtype: string

(b)cat中的索引對齊當前版本中,如果兩邊合併的索引不相同且未指定join參數,默認為左連接,設置join='left'
s2 = pd.Series(list('abc'),index=[1,2,3],dtype='string')s2

1 a
2 b
3 c
dtype: string

0 ab*
1 *a
2 db
dtype: string

三、替換廣義上的替換,就是指str.replace函數的應用,fillna是針對缺失值的替換,上一章已經提及。提到替換,就不可避免地接觸到正則表達式,這裡默認讀者已掌握常見正則表達式知識點,若對其還不了解的,可以通過這份資料來熟悉3.1 str.replace的常見用法
s = pd.Series(['A', 'B', 'C', 'Aaba', 'Baca','', np.nan, 'CABA', 'dog', 'cat'],dtype="string")s

0 A
1 B
2 C
3 Aaba
4 Baca
5
6 <NA>
7 CABA
8 dog
9 cat
dtype: string

第一個值寫r開頭的正則表達式,後一個寫替換的字符串
s.str.replace(r'^[AB]','***')

0 ***
1 ***
2 C
3 ***aba
4 ***aca
5
6 <NA>
7 CABA
8 dog
9 cat
dtype: string

3.2 子組與函數替換通過正整數調用子組(0返回字符本身,從1開始才是子組)
s.str.replace(r'([ABC])(\w+)',lambda x:x.group(2)[1:]+'*')

0 A
1 B
2 C
3 ba*
4 ca*
5
6 <NA>
7 BA*
8 dog
9 cat
dtype: string

利用?P<....>表達式可以對子組命名調用
s.str.replace(r'(?P<one>[ABC])(?P<two>\w+)',lambda x:x.group('two')[1:]+'*')

0 A
1 B
2 C
3 ba*
4 ca*
5
6 <NA>
7 BA*
8 dog
9 cat
dtype: string

3.3 關於str.replace的注意事項首先,要明確str.replace和replace並不是一個東西:str.replace針對的是object類型或string類型,默認是以正則表達式為操作,目前暫時不支持DataFrame上使用;replace針對的是任意類型的序列或數據框,如果要以正則表達式替換,需要設置regex=True,該方法通過字典可支持多列替換。但現在由於string類型的初步引入,用法上出現了一些問題,這些issue有望在以後的版本中修復。(a)str.replace賦值參數不得為pd.NA這聽上去非常不合理,例如對滿足某些正則條件的字符串替換為缺失值,直接更改為缺失值在當下版本就會報錯
#pd.Series(['A','B'],dtype='string').str.replace(r'[A]',pd.NA) #pd.Series(['A','B'],dtype='O').str.replace(r'[A]',pd.NA) 

此時,可以先轉為object類型再轉換回來,曲線救國:

pd.Series(['A','B'],dtype='string').astype('O').replace(r'[A]',pd.NA,regex=True).astype('string')

0 <NA>
1 B
dtype: string

至於為什麼不用replace函數的regex替換(但string類型replace的非正則替換是可以的),原因在下面一條(b)對於string類型Series在使用replace函數時不能使用正則表達式替換,該bug現在還未修復
pd.Series(['A','B'],dtype='string').replace(r'[A]','C',regex=True)

0 A
1 B
dtype: string

pd.Series(['A','B'],dtype='O').replace(r'[A]','C',regex=True)

0 C
1 B
dtype: object

(c)string類型序列如果存在缺失值,不能使用replace替換
#pd.Series(['A',np.nan],dtype='string').replace('A','B') 

pd.Series(['A',np.nan],dtype='string').str.replace('A','B')

0 B
1 <NA>
dtype: string

綜上,概況的說,除非需要賦值元素為缺失值(轉為object再轉回來),否則請使用str.replace方法四、子串匹配與提取4.1 str.extract方法(a)常見用法
pd.Series(['10-87', '10-88', '10-89'],dtype="string").str.extract(r'([\d]{2})-([\d]{2})')

使用子組名作為列名

pd.Series(['10-87', '10-88', '-89'],dtype="string").str.extract(r'(?P<name_1>[\d]{2})-(?P<name_2>[\d]{2})')

利用?正則標記選擇部分提取

pd.Series(['10-87', '10-88', '-89'],dtype="string").str.extract(r'(?P<name_1>[\d]{2})?-(?P<name_2>[\d]{2})')

pd.Series(['10-87', '10-88', '10-'],dtype="string").str.extract(r'(?P<name_1>[\d]{2})-(?P<name_2>[\d]{2})?')

(b)expand參數(默認為True)

對於一個子組的Series,如果expand設置為False,則返回Series,若大於一個子組,則expand參數無效,全部返回DataFrame。對於一個子組的Index,如果expand設置為False,則返回提取後的Index,若大於一個子組且expand為False,報錯。
s = pd.Series(["a1", "b2", "c3"], ["A11", "B22", "C33"], dtype="string")s.index

Index(['A11', 'B22', 'C33'], dtype='object')

s.str.extract(r'([\w])',expand=False)

A11 a
B22 b
C33 c
dtype: string

s.index.str.extract(r'([\w])')

s.index.str.extract(r'([\w])',expand=False)

Index(['A', 'B', 'C'], dtype='object')

s.index.str.extract(r'([\w])([\d])')

#s.index.str.extract(r'([\w])([\d])',expand=False) 

4.2 str.extractall方法與extract只匹配第一個符合條件的表達式不同,extractall會找出所有符合條件的字符串,並建立多級索引(即使只找到一個)
s = pd.Series(["a1a2", "b1", "c1"], index=["A", "B", "C"],dtype="string")two_groups = '(?P<letter>[a-z])(?P<digit>[0-9])'s.str.extract(two_groups, expand=True)

s.str.extractall(two_groups)

s['A']='a1's.str.extractall(two_groups)

如果想查看第i層匹配,可使用xs方法

s = pd.Series(["a1a2", "b1b2", "c1c2"], index=["A", "B", "C"],dtype="string")s.str.extractall(two_groups).xs(1,level='match')

4.3 str.contains和str.match前者的作用為檢測是否包含某種正則模式
pd.Series(['1', None, '3a', '3b', '03c'], dtype="string").str.contains(r'[0-9][a-z]')

0 False
1 <NA>
2 True
3 True
4 True
dtype: boolean

可選參數為na
pd.Series(['1', None, '3a', '3b', '03c'], dtype="string").str.contains('a', na=False)

0 False
1 False
2 True
3 False
4 False
dtype: boolean

str.match與其區別在於,match依賴於python的re.match,檢測內容為是否從頭開始包含該正則模式
pd.Series(['1', None, '3a_', '3b', '03c'], dtype="string").str.match(r'[0-9][a-z]',na=False)

0 False
1 False
2 True
3 True
4 False
dtype: boolean

pd.Series(['1', None, '_3a', '3b', '03c'], dtype="string").str.match(r'[0-9][a-z]',na=False)

0 False
1 False
2 False
3 True
4 False
dtype: boolean

五、常用字符串方法5.1 過濾型方法(a)str.strip常用於過濾空格
pd.Series(list('abc'),index=[' space1  ','space2  ','  space3'],dtype="string").index.str.strip()

Index(['space1', 'space2', 'space3'], dtype='object')

(b)str.lower和str.upper
pd.Series('A',dtype="string").str.lower()

0 a
dtype: string

pd.Series('a',dtype="string").str.upper()

0 A
dtype: string

(c)str.swapcase和str.capitalize分別表示交換字母大小寫和大寫首字母
pd.Series('abCD',dtype="string").str.swapcase()

0 ABcd
dtype: string

pd.Series('abCD',dtype="string").str.capitalize()

0 Abcd
dtype: string

5.2 isnumeric方法檢查每一位是否都是數字,請問如何判斷是否是數值?(問題二)
pd.Series(['1.2','1','-0.3','a',np.nan],dtype="string").str.isnumeric()

0 False
1 True
2 False
3 False
4 <NA>
dtype: boolean

六、問題與練習6.1 問題【問題一】 str對象方法和df/Series對象方法有什麼區別?

【問題二】 給出一列string類型,如何判斷單元格是否是數值型數據?

【問題三】 rsplit方法的作用是什麼?它在什麼場合下適用?

【問題四】 在本章的第二到第四節分別介紹了字符串類型的5類操作,請思考它們各自應用於什麼場景?

6.2 練習【練習一】 現有一份關於字符串的數據集,請解決以下問題:(a)現對字符串編碼存儲人員信息(在編號後添加ID列),使用如下格式:「×××(名字):×國人,性別×,生於×年×月×日」
> ex1_ori = pd.read_csv('data/String_data_one.csv',index_col='人員編號')> ex1_ori.head()  姓名  國籍  性別  出生年  出生月  出生日人員編號            1  aesfd  2  男  1942  8  102  fasefa  5  女  1985  10  43  aeagd  4  女  1946  10  154  aef  4  男  1999  5  135  eaf  1  女  2010  6  24
> ex1 = ex1_ori.copy()> ex1['冒號'] = ':'> ex1['逗號'] = ','> ex1['國人'] = '國人'> ex1['性別2'] = '性別'> ex1['生於'] = '生於'> ex1['年'] = '年'> ex1['月'] = '月'> ex1['日'] = '日'> ID = ex1['姓名'].str.cat([ex1['冒號'], ex1['國籍'].astype('str'), ex1['國人'], ex1['逗號'], ex1['性別2'], ex1['性別'], ex1['逗號'], ex1['生於'], ex1['出生年'].astype('str'), ex1['年'], ex1['出生月'].astype('str'), ex1['月'], ex1['出生日'].astype('str'), ex1['日'] ])> ex1_ori['ID'] = ID> ex1_ori 姓名 國籍 性別 出生年 出生月 出生日 ID人員編號 1 aesfd 2 男 1942 8 10 aesfd:2國人,性別男,生於1942年8月10日2 fasefa 5 女 1985 10 4 fasefa:5國人,性別女,生於1985年10月4日3 aeagd 4 女 1946 10 15 aeagd:4國人,性別女,生於1946年10月15日4 aef 4 男 1999 5 13 aef:4國人,性別男,生於1999年5月13日5  eaf  1  女  2010  6  24  eaf:1國人,性別女,生於2010年6月24日

(b)將(a)中的人員生日信息部分修改為用中文表示(如一九七四年十月二十三日),其餘返回格式不變。

(c)將(b)中的ID列結果拆分為原列表相應的5列,並使用equals檢驗是否一致。
> dic_year = {i[0]:i[1] for i in zip(list('零一二三四五六七八九'),list('0123456789'))}> dic_two = {i[0]:i[1] for i in zip(list('十一二三四五六七八九'),list('0123456789'))}> dic_one = {'十':'1','二十':'2','三十':'3',None:''}> df_res = df_new['ID'].str.extract(r'(?P<姓名>[a-zA-Z]+):(?P<國籍>[\d])國人,性別(?P<性別>[\w]),生於(?P<出生年>[\w]{4})年(?P<出生月>[\w]+)月(?P<出生日>[\w]+)日')> df_res['出生年'] = df_res['出生年'].str.replace(r'(\w)+',lambda x:''.join([dic_year[x.group(0)[i]] for i in range(4)]))> df_res['出生月'] = df_res['出生月'].str.replace(r'(?P<one>\w?十)?(?P<two>[\w])',lambda x:dic_one[x.group('one')]+dic_two[x.group('two')]).str.replace(r'0','10')> df_res['出生日'] = df_res['出生日'].str.replace(r'(?P<one>\w?十)?(?P<two>[\w])',lambda x:dic_one[x.group('one')]+dic_two[x.group('two')]).str.replace(r'^0','10')> df_res.head()  姓名  國籍  性別  出生年  出生月  出生日人員編號            1  aesfd  2  男  1942  8  102  fasefa  5  女  1985  10  43  aeagd  4  女  1946  10  154  aef  4  男  1999  5  135  eaf  1  女  2010  6  24

【練習二】 現有一份半虛擬的數據集,第一列包含了新型冠狀病毒的一些新聞標題,請解決以下問題:

(a)選出所有關於北京市和上海市新聞標題的所在行。

(b)求col2的均值。
ex2.col2.str.rstrip('-`').str.lstrip('/').astype(float).mean()

-0.984

(c)求col3的均值。
ex2.columns = ex2.columns.str.strip(' ')
def is_number(x): try: float(x) return True except (SyntaxError, ValueError) as e: return Falseex2[~ex2.col3.map(is_number)]

 ex2.col3.str.replace(r'[`\\{]', '').astype(float).mean()

24.707484999999988

獲取一折本站知識星球優惠券,複製連結直接打開:

https://t.zsxq.com/yFQV7am

本站qq群1003271085。

加入微信群請掃碼進群:

相關焦點

  • Pandas對文本數據處理
    在處理數據的時候,對數值型的數據處理還是比較方便的,但是有時候數值型數據出現問題後就會比較頭痛了,因為文本數據的排列組合可是有很多很多的,今天我們就學習一下如何對文本數據進行處理,這樣我們接下來在工作中遇到了這些情況就可以少掉一下頭髮啦。
  • Python數學建模技巧之pandas數據處理
    最常見的庫有進行矩陣運算的Numpy、進行數據處理的pandas、進行科學計算的Scipy、進行圖形繪製及科學可視化的matplotlib、進行符號計算的Sympy以及方便進行機器學習任務的Sklearn。由於今年美賽官方公告中稱,將會提前在賽題公布之前就提供下載C題數據集的方式。
  • Python數據分析之pandas數據讀寫
    引言我們現在已經基本熟悉了pandas庫以及它所提供的用於數據分析的基礎功能,也知道了DataFrame和Series是這個庫的核心,數據處理、計算和分析都是圍繞他們展開的。你首先會學會文本文件的讀寫,隨後再逐步過渡到更加複雜的二進位文件。最後我們會講解SQL和NoSQL常用資料庫的連接方法,我們用幾個例子來說明如何直接把DataFrame中的數據存儲到資料庫中。同時,我們還會介紹如何從資料庫讀取數據,存儲為DataFrame對象,並對其進行檢索。
  • Python數據分析:pandas讀取和寫入數據
    平時工作中,我們會接觸到不同的數據文件,比如很常見的excel文件(後綴名為xls和xlsx),csv、txt等文本文件,json文件以及sql文件等等。pandas讀取這些數據文件的方法如表格所示:01讀取寫入文本文件read_csv()方法用來讀取 csv格式的數據文件,read_table()方法則是讀取通用分隔符分隔的數據文件,它們的參數相同。
  • Python數據處理庫pandas入門教程
    pandas是一個Python語言的軟體包,在我們使用Python語言進行機器學習編程的時候,這是一個非常常用的基礎編程庫。
  • 如何使用Python 和 Pandas讀寫JSON文件
    JSON是JavaScript對象表示法的縮寫,是一種緊湊的、基於文本的格式,用於交換數據。這種格式通常用於通過所謂的Web API來從web伺服器下載和存儲信息。JSON是一種基於文本的格式,在打開一個JSON文件時,我們將識別出其結構。也就是說,它與Python的字典結構沒有太大的不同。
  • 如何用pandas對excel中的文本數據進行操作
    excel進行數據的操作最便捷的庫是pandas,但是如何使用pandas對excel中的文本進行清洗,這是一個很技巧性的工作。
  • 《pandas數據讀取》
    今天呢就給大家分享一個數據分析裡面的基礎內容之pandas數據讀取 數據讀取是進行數據預處理,建模與分析的前提,不同的數據源
  • Python數據核對系列之2—power query VS pandas
    它需要用列表形式展示。{"GID"},大括號就是query的列表table2,key2同上newColumnName as Text :設置文本格式的新列名。它會把關聯生成的數據存儲在這個列裡。我們的例子中就是ERP列。
  • 如何使用Python批量化處理Excel——零基礎入門指南
    Python也是這樣的,它已經有了非常強大和完備的函數庫,我們只需要調用函數,然後修改參數,就可以用Python來處理我們自己的表格,它與Excel的區別無非就是沒有可視化圖形界面而已,你選不中單元格,沒有各種菜單選項給你點,你只能手動敲擊文本,但當你學習明白函數、參數、返回值、變量等概念,你就能像使用excel那樣使用命令行來進行python編程,並驚嘆於其強大。
  • 如何快速學會Python處理數據?(5000字走心總結)
    今天我分享一些自己學習Python的心得,並用一個案例來說明python解決問題的基本思路和框架。1 如何學好Python 1.1 明確自己的需求(最好是剛需)聽到別人說Python很牛很厲害,也想跟著學,這樣的人肯定是學不好python的。沒有明確的需求和動力,就會導致你學python兩天打魚三天曬網,沒有恆心也沒有決心。
  • python-pandas讀寫csv數據
    可以是單個名稱/數字或由多個名稱/數字組成的列表(層次化索引)error_bad_lines = False # 當某行數據有問題時,不報錯,直接跳過,處理髒數據時使用 na_values = 'NULL' # 將NULL識別為空值encoding='utf-8' #指明讀取文件的編碼,默認utf-8說明:① 讀取csv/txt/tsv文件,返回一個DataFrame類型的對象。
  • 數據處理基礎2
    Python 數據處理基礎:Part 2source: https://realpython.com/
  • 數據科學 | pandas數據導入與導出
    當我們開始著手做一個數據分析項目時,選擇和導入數據集是第一個步驟,而導出數據雖然非必需,但有時候我們也需要保存處理或者分析後的結果,方便下次使用。在pandas中,它已經為我們提供了很多不同格式數據的導入和導出方法,下面這篇文章將具體介紹一些較為常用的方法,包括excel、csv文件以及資料庫的導入導出等。數據導入和導出是pandas中很基礎且重要的一個部分。
  • 「Python替代Excel Vba」系列(三):pandas處理不規範數據
    帶你用pandas玩轉各種數據處理前言本系列前2篇已經稍微展示了 python 在數據處理方面的強大能力,這主要得益於 pandas 包的各種靈活處理方式。但是身經百戰的你肯定會覺得,前2篇例子中的數據太規範了,如果把數據導入到資料庫還是可以方便解決問題的。因此,本文將使用稍微複雜的數據做演示,充分說明 pandas 是如何靈活處理各種數據。
  • Python學習120課 pandas簡介kaggle下載數據及pandas讀取外部數據
    【每天幾分鐘,從零入門python編程的世界!】numpy的基本的東西我們學習差不多了,後面具體應用中遇到問題具體分析,然後去深入了解遇到的新的知識點就行。現在我們開始學習pandas,pandas一般用的更多,pandas是基於numpy去寫的。pandas是一個專門做數據結構和數據分析的庫。
  • 如何用Pandas處理文本數據?
    每日乾貨 & 每月組隊學習,不錯過作者:耿遠昊,Datawhale成員,華東師範大學文本數據是指不能參與算術運算的任何字符,也稱為字符型數據。文本數據具有數據維度高、數據量大且語義複雜等特點,是一種較為複雜的數據類型。今天,我們就來一起看看如何使用Pandas對文本數據進行數據處理。本文目錄    1. string類型的性質        1.1. string與object的區別        1.2. string類型的轉換    2.
  • python數據分析萬字乾貨!一個數據集全方位解讀pandas
    說到python與數據分析,那肯定少不了pandas的身影,本文希望通過分析經典的NBA數據集來系統的全方位講解pandas包,建議搭配IDE一遍敲一邊讀哦。話不多說,開始吧!但是,如何確定數據集包含NBA的哪些統計數據?
  • python基礎知識變量、運算和數據類型
    昨天搭建好juypter notebook,並錄製了第一堂python的課程,簡單講解了python的歷史,以及python可以幫助我們如何提供效率。字符串字符串或串(String)是用於處理文本的數據類型:一般用單引號' ',雙引號" ",三單引號''' ''',三雙引號""" """來標識字符串,三引號用於多行文本;字符串常用的方法:方法功能capitalize() 大寫句首的字母 upper() 將小寫字母變成大寫字母
  • Python自動化用這些知識點就夠了!
    這可能是很多非IT職場人士面臨的困惑,想把python用到工作中,卻不知如何下手?python在自動化辦公領域越來越受歡迎,批量處理簡直是加班族的福音。excel自動化office家族其實都可以用VBA解決自動化的問題,但可能很多人不會用。python針對excel有很多的第三方庫可以用,比如xlwings、xlsxwriter、xlrd、xlwt、pandas、xlsxwriter、win32com、xlutils等等。