datawhale學習第二章 pandas基礎
import numpy as np
import pandas as pd
之前的版本號是1.0.5
使用pip install --upgrade pandas
更新即可
一、檔案的讀取和寫入
1. 檔案讀取
pandas
可以讀取的檔案格式有很多,這裡主要介紹讀取csv, excel, txt
檔案。
即pd.read_csv
pd.read_table
pd.read_excel
1.1pd.read_csv
pandas.read_csv(filepath_or_buffer, sep=', ', delimiter=None, header='infer' , names=None, index_col=None, usecols=None, squeeze=False, prefix=None, mangle_dupe_cols=True, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skipinitialspace=False, skiprows=None, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, skip_blank_lines= True, parse_dates=False, infer_datetime_format=False, keep_date_col=False, date_parser=None, dayfirst=False, iterator=False, chunksize=None, compression='infer', thousands=None, decimal=b'.', lineterminator=None, quotechar='"', quoting=0, escapechar=None, comment=None, encoding=None, dialect=None , tupleize_cols=None, error_bad_lines=True, warn_bad_lines=True, skipfooter=0, doublequote=True, delim_whitespace=False, low_memory=True, memory_map=False, float_precision=None)
具體引數詳解參考:pandas引數詳解
1.2pd.read_table
pandas.read_table(filepath_or_buffer,sep='\t',delimiter=None,header='infer',names=None,
index_col=None,usecols=None,squeeze=False,prefix=None,mangle_dupe_cols=True,dtype=None,
engine=None,converters=None,true_values=None,false_values=None,skipinitialspace=False,
skiprows=None,nrows=None,na_values=None,keep_default_na=True,na_filter=True,
verbose=False,skip_blank_lines=True,parse_dates=False,infer_datetime_format=False,
keep_date_col=False,date_parser=None,dayfirst=False,iterator=False,chunksize=None,
compression='infer',thousands=None,decimal=b'.',lineterminator=None,quotechar='"',
quoting=0,escapechar=None,comment=None,encoding=None,dialect=None,tupleize_cols=None,
error_bad_lines=True,warn_bad_lines=True,skipfooter=0,doublequote=True,
delim_whitespace=False,low_memory=True,memory_map=False,float_precision=None)
和pandas.read_csv
引數類似,可以看到前者sep=‘,’
後者sep='\t'
1.3pd.read_excel
pd.read_excel(io, sheet_name=0, header=0, names=None, index_col=None, usecols=None, squeeze=False, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skiprows=None, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, parse_dates=False, date_parser=None, thousands=None, comment=None, skipfooter=0, convert_float=True, mangle_dupe_cols=True)
引數詳解:
1.io引數
io引數可以接受的有:str,Excel檔案,xlrd.Book,路徑物件或類似檔案的物件,其中最常用的是str,一般是檔案路徑+檔名,需要注意的是檔名字不要漏掉字尾,即副檔名,表明檔案型別的那個!有時候需要對路徑中的”\”進行轉義,io引數沒有預設值,必須傳入。
2.sheet_name引數
sheet_name引數可以接收的有:str,int,list或None,預設0
其中,字串用於工作表名稱。 整數用於零索引工作表位置。 字串/整數列表用於請求多個工作表。設定None獲取所有工作表。
有時候一個excel工作簿中包含有很多個sheet工作表,如果不指定預設為0,資料讀入的時候預設讀入的是第一個位置的sheet。0就是排在第一個位置的sheet,1是排在第二位置的sheet,依次類推。
也可以傳入列表[0,1],輸出的結果是Dict,裡面存入兩個sheet的內容。
df_excel1=pd.read_excel('../data/my_excel.xlsx', sheet_name=[0,1])
type(df_excel1) #Dict
3.header引數
這個引數是用來指定哪一行作為列名的,預設是第0行,接收的引數可以是整數(指定第幾行作為列名),可以是有整陣列成的列表(指定哪幾行作為列名,是的,列名可以有多行,是不是有點突破認知?),也可以是None(沒有列名)。
4.names引數
官方文件說這個引數接收 array-like, 預設 None,表示要使用的列名列表,如果不需要列名,請設定header = None,如果header = None和names引數都設定的話,依然會顯示names指定的列名。
5.usecols引數
該引數接收字元或者類似列表的序列,預設值是None,返回的是列的子集,直白點解釋就是在讀入表格的時候不是所有的列都會被讀入,可以通過usecols引數來設定要把哪些列讀取進來。
如果是None,表示所有的列都會被讀取。
如果是列表,表示選取指定的列讀取,比如像要只讀入第n列,這樣就可以usecols=[n],如果是多列,就把多個整數放入一個列表中傳遞給引數。需要留心的是,列表中不止可以傳入整數,也可以是欄位名組成的列表。
如果是str,則可以用A表示第一列,依次類推。例如‘A,B’或者‘A,B,E:F’
注意:如果設定了names引數,注意設定的列名個數要和讀取的列數一致
這裡有一些常用的公共引數,header=None
表示第一行不作為列名,index_col
表示把某一列或幾列作為索引,索引的內容將會在第三章進行詳述,usecols
表示讀取列的集合,預設讀取所有的列,parse_dates
表示需要轉化為時間的列,關於時間序列的有關內容將在第十章講解,nrows
表示讀取的資料行數。上面這些引數在上述的三個函式裡都可以使用。
pd.read_csv('../data/my_csv.csv', index_col=['col1', 'col2'])
pd.read_csv('../data/my_csv.csv', index_col=[0,1])
pd.read_excel('../data/my_excel.xlsx', index_col=[0,1])
區別:pd.read_excel中index_col中只能傳入元素是整數的列表
這裡用的都是相對路徑引用。
在讀取 txt
檔案時,經常遇到分隔符非空格的情況, read_table
有一個分割引數 sep
,它使得使用者可以自定義分割符號,進行 txt
資料的讀取。例如,下面的讀取的表以 ||||
為分割:
上面的結果顯然不是理想的,這時可以使用sep
,同時需要指定引擎為python
:
注意:sep是正則引數
在使用read_table
的時候需要注意,引數sep
中使用的是正則表示式,因此需要對|
進行轉義變成\|
,否則無法讀取到正確的結果。
2. 資料寫入
一般在資料寫入中,最常用的操作是把index
設定為False
,特別當索引沒有特殊意義的時候,這樣的行為能把索引在儲存的時候去除。
df_csv.to_csv('../data/my_csv_saved.csv', index=False)
df_excel.to_excel('../data/my_excel_saved.xlsx', index=False)
pandas
中沒有定義to_table
函式,但是to_csv
可以儲存為txt
檔案,並且允許自定義分隔符,常用製表符\t
分割:
df_txt.to_csv('../data/my_txt_saved.txt', sep='\t', index=False)
與上面pd.read_csv()與pd.read_table()的區別對應,sep不一樣。
如果想要把表格快速轉換為markdown
和latex
語言,可以使用to_markdown
和to_latex
函式,此處需要安裝tabulate
包。
二、基本資料結構
pandas
中具有兩種基本的資料儲存結構,儲存一維values
的Series
和儲存二維values
的DataFrame
,在這兩種結構上定義了很多的屬性和方法。
1. Series
Series
一般由四個部分組成,分別是序列的值data
、索引index
、儲存型別dtype
、序列的名字name
。其中,索引也可以指定它的名字,預設為空。
s = pd.Series(data = [100, 'a', {'dic1':5}], #序列的值
index = pd.Index(['id1', 20, 'third'], name='my_idx'), #指定index的名字
dtype = 'object', #指定儲存型別
name = 'my_name') #序列的名字
s
'''my_idx
id1 100
20 a
third {'dic1': 5}
Name: my_name, dtype: object'''
【NOTE】object
型別
object
代表了一種混合型別,正如上面的例子中儲存了整數、字串以及Python
的字典資料結構。此外,目前pandas
把純字串序列也預設認為是一種object
型別的序列,但它也可以用string
型別儲存。
pd.Series()可以用字典結構為引數。
s=pd.Series({'a':1,'b':2,'c':3,'f':4,'e':5})
pd.Series的這些屬性可以通過.的方式來獲取:
還有pd.Series.is_monotonic
返回一個布林值(若值是單調遞增的則返回True)
pd.Series.is_monotonic_decreasing
是單調遞減返回True
pd.Series.is_monotonic_increasing
與第一個一樣
索引是pandas
中最重要的概念之一,它將在第三章中被詳細地討論。如果想要取出單個索引對應的值,可以通過[index_item]
可以取出。
2. DataFrame
DataFrame
在Series
的基礎上增加了列索引columns
,一個數據框可以由二維的data
與行列索引來構造:
但一般而言,更多的時候會採用從列索引名到資料的對映來構造資料框,同時再加上行索引:
這裡的data還可以傳入ndarray等
由於這種對映關係,在DataFrame
中可以用[col_name]
與[col_list]
來取出相應的列與由多個列組成的表,結果分別為Series
和DataFrame
:
注意:DataFrame在取相應的列時,當傳入的是[col_name_1,col_name_2](一個list)時,返回的是DataFrame,而只是傳入一個col_name,則返回的是Series
與Series
類似,在資料框中同樣可以取出相應的屬性:
通過.T可以把DataFrame進行轉置(Series也有.T屬性,返回的就是自身):
三、常用基本函式
為了進行舉例說明,在接下來的部分和其餘章節都將會使用一份learn_pandas.csv
的虛擬資料集,它記錄了四所學校學生的體測個人資訊。
上述列名依次代表學校、年級、姓名、性別、身高、體重、是否為轉系生、體測場次、測試時間、1000米成績,本章只需使用其中的前七列,則用上面提到的方法。
1. 彙總函式
head, tail
函式分別表示返回表或者序列的前n
行和後n
行,其中n
預設為5:
info, describe
分別返回表的資訊概況和表中數值列對應的主要統計量 :
df.info()引數:
**verbose:**是否列印完整的摘要。 True或False會覆蓋顯示。
**buf:**可寫緩衝區,預設為sys.stdout
**max_cols:**類似控制是否列印完整的摘要,接收int
**memory_usage:**指定是否應顯示DataFrame元素(包括索引)的總記憶體使用情況。螢幕上將不顯示任何內容。True或False會覆蓋顯示。 “ deep”的值與True相同,具有自省性。記憶體使用情況以人類可讀的單位(以2為基數的表示形式)顯示。
**null_counts:**是否顯示非空計數。如果為None,則僅顯示框架是否小於max_info_rows和max_info_columns。如果為True,則始終顯示計數。如果為False,則從不顯示計數。
max_cols小於DataFrame的列時,類似於verbose=False。反之,類似於verbose=True
DataFrame.describe(percentiles=None, include=None,exclude=None,datetime_is_numeric=False)
其物理意義在於觀察這一系列資料的範圍。大小、波動趨勢等等,便於判斷後續對資料採取哪類模型更合適。
1.第一個percentiles,這個引數可以設定數值型特徵的統計量,預設是[.25, .5, .75],也就是返回25%,50%,75%資料量時的數字,但是這個可以修改的.預設是有50%的
2.第二個引數:include,這個引數預設是隻計算數值型特徵的統計量(這就是為什麼只有兩列的統計量),當輸入include=[‘O’],會計算離散型變數的統計特徵。此外傳引數是‘all’的時候會把數值型和離散型特徵的統計都進行顯示。
3.第三個引數的設計就更貼心了,第二個引數是你可以指定選那些,第三個引數就是你可以指定不選哪些,人性化設計。這個引數預設不丟棄任何列,相當於無影響。
【NOTE】更全面的資料彙總
info, describe
只能實現較少資訊的展示,如果想要對一份資料集進行全面且有效的觀察,特別是在列較多的情況下,推薦使用pandas-profiling包,它將在第十一章被再次提到。
2. 特徵統計函式
在Series
和DataFrame
上定義了許多統計函式,最常見的是sum, mean, median, var, std, max, min
。例如,選出身高和體重列進行演示:
此外,需要介紹的是quantile, count, idxmax
這三個函式,它們分別返回的是分位數、非缺失值個數、最大值對應的索引:
上面這些所有的函式,由於操作後返回的是標量,所以又稱為聚合函式,它們有一個公共引數axis
,預設為0代表逐列聚合,如果設定為1則表示逐行聚合:
3. 唯一值函式
對序列使用unique
和nunique
可以分別得到其唯一值組成的列表和唯一值的個數:
value_counts
可以得到唯一值和其對應出現的頻數:
如果想要觀察多個列組合的唯一值,可以使用drop_duplicates
。其中的關鍵引數是keep
,預設值first
表示每個組合保留第一次出現的所在行,last
表示保留最後一次出現的所在行,False
表示把所有重複組合所在的行剔除。
DataFrame.drop_duplicates(subset=None, keep='first', inplace=False, ignore_index=False)
df_demo.drop_duplicates(['Name', 'Gender'], keep=False) #結果是164X3
df_demo.drop_duplicates(['Name', 'Gender'], keep='last')#結果是181X3
從這裡可以看出keep=False,把所有重複的都刪掉了。
此外,inplace=Ture則在df上原地修改,不會返回一個df
此外,duplicated
和drop_duplicates
的功能類似,但前者返回了是否為唯一值的布林列表,其keep
引數與後者一致。其返回的序列,把重複元素設為True
,否則為False
。
就是和drop_duplicated一樣,只是duplicated返回的是布林值。 drop_duplicates
等價於把duplicated
為True
的對應行剔除。
4. 替換函式
一般而言,替換操作是針對某一個列進行的,因此下面的例子都以Series
舉例。pandas
中的替換函式可以歸納為三類:對映替換、邏輯替換、數值替換。其中對映替換包含replace
方法、第八章中的str.replace
方法以及第九章中的cat.codes
方法,此處介紹replace
的用法。
DataFrame.replace(to_replace=None,value=None,inplace=False,limit=None,regex=False,method='pad')
在replace
中,可以通過字典構造,或者傳入兩個列表來進行替換:
另外,replace
還有一種特殊的方向替換,指定method
引數為ffill
則為用前面一個最近的未被替換的值進行替換,bfill
則使用後面最近的未被替換的值進行替換。從下面的例子可以看到,它們的結果是不同的:
記憶:ffill->forward往前,bfill->back往後
最後,limit引數是規定ffill與bfill來往前或往後尋找值填充的最大gap,下面就是隻在後面一位填充
【WARNING】正則替換請使用str.replace
[¶](http://localhost:8888/notebooks/Documents/機器學習/datawhale/joyful-pandas-master/notebook/第二章 pandas基礎.ipynb#[WARNING]正則替換請使用str.replace)
雖然對於replace
而言可以使用正則替換,但是當前版本下對於string
型別的正則替換還存在bug
,因此如有此需求,請選擇str.replace
進行替換操作,具體的方式將在第八章中講解。
邏輯替換包括了where
和mask
,這兩個函式是完全對稱的:where
函式在傳入條件為False
的對應行進行替換,而mask
在傳入條件為True
的對應行進行替換,當不指定替換值時,替換為缺失值。
需要注意的是,傳入的條件只需是與被呼叫的Series
索引一致的布林序列即可:
數值替換包含了round, abs, clip
方法,它們分別表示按照給定精度四捨五入、取絕對值和截斷:
【練一練】
在 clip 中,超過邊界的只能截斷為邊界值,如果要把超出邊界的替換為自定義的值,應當如何做?
5. 排序函式
排序共有兩種方式,其一為值排序,其二為索引排序,對應的函式是sort_values
和sort_index
。
為了演示排序函式,下面先利用set_index
方法把年級和姓名兩列作為索引,多級索引的內容和索引設定的方法將在第三章進行詳細講解。
對身高進行排序,預設引數ascending=True
為升序:
在排序中,經常遇到多列排序的問題,比如在體重相同的情況下,對身高進行排序,並且保持身高降序排列,體重升序排列:
這裡就是先對Weight排序,在對Height排序,其中前者是升序後者是降序。注意這裡引數傳入的是列表。
索引排序的用法和值排序完全一致,只不過元素的值在索引中,此時需要指定索引層的名字或者層號,用引數level
表示。另外,需要注意的是字串的排列順序由字母順序決定。
6. apply方法
apply
方法常用於DataFrame
的行迭代或者列迭代,它的axis
含義與第2小節中的統計聚合函式一致,apply
的引數往往是一個以序列為輸入的函式。例如對於.mean()
,使用apply
可以如下地寫出:
同樣的,可以利用lambda
表示式使得書寫簡潔,這裡的x
就指代被呼叫的df_demo
表中逐個輸入的序列。
若指定axis=1
,那麼每次傳入函式的就是行元素組成的Series
,其結果與之前的逐行均值結果一致。
這裡再舉一個例子:mad
函式返回的是一個序列中偏離該序列均值的絕對值大小的均值,例如序列1,3,7,10中,均值為5.25,每一個元素偏離的絕對值為4.25,2.25,1.75,4.75,這個偏離序列的均值為3.25。現在利用apply
計算升高和體重的mad
指標:
【WARNING】謹慎使用apply
得益於傳入自定義函式的處理,apply
的自由度很高,但這是以效能為代價的。一般而言,使用pandas
的內建函式處理和apply
來處理同一個任務,其速度會相差較多,因此只有在確實存在自定義需求的情境下才考慮使用apply
。
四、視窗物件
pandas
中有3類視窗,分別是滑動視窗rolling
、擴張視窗expanding
以及指數加權視窗ewm
。需要說明的是,以日期偏置為視窗大小的滑動視窗將在第十章討論,指數加權視窗見本章練習。
1. 滑窗物件
要使用滑窗函式,就必須先要對一個序列使用.rolling
得到滑窗物件,其最重要的引數為視窗大小window
。
得到了一個Rolling物件。
在得到了滑窗物件後,能夠使用相應的聚合函式進行計算,需要注意的是視窗包含當前行所在的元素,例如在第四個位置進行均值運算時,應當計算(2+3+4)/3,而不是(1+2+3)/3:
對於滑動相關係數或滑動協方差的計算,可以如下寫出:
roller.cov(s2)第三個值2.5 就是(1,2,3)與(1,2,6)的cov,往後依次滑動。
此外,還支援使用apply
傳入自定義函式,其傳入值是對應視窗的Series
,例如上述的均值函式可以等效表示:
shift, diff, pct_change
是一組類滑窗函式,它們的公共引數為periods=n
,預設為1,分別表示取向前第n
個元素的值、與向前第n
個元素做差(與Numpy
中不同,後者表示n
階差分)、與向前第n
個元素相比計算增長率。這裡的n
可以為負,表示反方向的類似操作。
這裡的增加率計算:設當前索引為k, p c t = s [ k ] − s [ k − n ] s [ k − n ] pct=\frac{s[k]-s[k-n]}{s[k-n]} pct=s[k−n]s[k]−s[k−n]
將其視作類滑窗函式的原因是,它們的功能可以用視窗大小為n+1
的rolling
方法等價代替:
【練一練】
rolling
物件的預設視窗方向都是向前的,某些情況下使用者需要向後的視窗,例如對1,2,3設定向後窗口為2的sum
操作,結果為3,5,NaN,此時應該如何實現向後的滑窗操作?
2. 擴張視窗
擴張視窗又稱累計視窗,可以理解為一個動態長度的視窗,其視窗的大小就是從序列開始處到具體操作的對應位置,其使用的聚合函式會作用於這些逐步擴張的視窗上。具體地說,設序列為a1, a2, a3, a4,則其每個位置對應的視窗即[a1]、[a1, a2]、[a1, a2, a3]、[a1, a2, a3, a4]。
【練一練】
cummax, cumsum, cumprod
函式是典型的類擴張視窗函式,請使用expanding
物件依次實現它們。