【資料分析】:python:Pandas基礎:結構化資料處理
阿新 • • 發佈:2019-01-30
目錄:
一 pandas及其重要性
- pandas是資料分析工作的首選庫。它含有使資料分析工作變得更快更簡單的高階資料結構和操作工具。
- pandas是基於Numpy構建的讓以Numpy為中心的應用變得更加簡單。
- 它能滿足工作中的許多需求:
① 具備按軸自動或顯式資料對齊功能的資料結構。防止由於資料未對齊導致的常見錯誤。
② 整合時間序列功能。
③ 技既能處理時間序列也能處理非時間序列資料的資料結構。
④ 數學運算和簡約(agg),可以根據不同的元資料(軸編號)處理。
⑤ 靈活處理缺失資料。
⑥ 合併及其他出現在常見資料庫中的關係型運算。 - pandas可以解決的資料問題隨著它的庫規模的增大而變得更加強大,成為資料分析一個不可或缺的工具。
二 pandas的資料結構介紹
1 Series
- Series是一種類似於一維陣列的物件,它由一組資料(各種Numpy資料型別)以及一組與之相關的資料標籤(即索引)組成。由一組資料即可產生最簡單的Series。
- Series的字串表現形式為:索引在左邊,值在右邊。自動建立一個0~N-1的整數型索引,可以通過values和index屬性獲取其陣列表示形式和索引物件。
obj = Series([4,7,-5,3])
obj.index
obj.values
- 可以通過索引的方式選取Series的單個或者一組值。
obj['one'] = 1
- 陣列運算(如根據布林型陣列進行過濾、標量乘法、應用數學函式等)會保留索引與值之間的連結。
obj[obj > 0]
obj * 2
np.exp(obj)
- 可以將Series看作一個定長的有序字典,索引到值之間是一個對映。
'a' in obj
- 如果資料被存放在一個python字典中,也可以直接通過這個字典建立Series。
data = {'one':1,'two':2,'three':3}
obj = Series(data)
- 如果只傳入一個字典,則結果Series的索引就是原字典的鍵(有序排列)。
- Series最重要的一個功能是:它在算術運算中會自動對齊不同索引的資料。
- Series物件本身及其索引都有一個name屬性,該屬性跟pandas其他的關鍵功能關係非常密切:
obj.name = ' population'
obj.index.name = 'state'
obj.index = ['one','two','three','four'] #通過賦值的方式修改索引
2 DataFrame
- DataFrame是一個表格型的資料結構,含有一組有序的列,每列可以是不同的值型別(數值、字串、布林值等)。
- DataFrame既有行索引也有列索引,可以被看做是Series組成的字典(共同用一個索引)。DataFrame面向行和列的操作基本上是平衡的。
- DataFrame中的資料是以一個或多個二維塊存放的(而不是列表、字典或別的一維資料結構)。也可以輕鬆地將其表示為更高維度的資料(層次化索引的表格型結構,高階資料處理功能的關鍵要素)。
- 構建DataFrame的方法①:直接傳入一個由等長列或Numpy陣列組成的字典。
data = ({'':[],
'':[]
'':[]})
frame = DataFrame(data)
- 結果DataFrame會自動加上索引,且全部列會被有序排列。
- 如果指定了列序列,則DataFrame的列會按照指定順序進行排列。
DataFrame(data,columns = ['one','two','three'])
frame = DataFrame(data,columns = [],index = [])
frame.columns
- 如果傳入的資料找不到,就會產生NA值
- 通過類似字典標記的方式或屬性的方式,可以將DataFrame的列獲取為一個Series
frame['one']
frame.one
- 返回的Series擁有原DataFrame相同的索引,且其name屬性也已經被相應的設定好。
- 行也可以通過位置或名稱的方式就行獲取,比如用索引欄位ix。
frame.ix['1']
- 列可以通過賦值的方式進行修改。
- 為不存在的列賦值會建立一個新列。
frame['new'] = 1 #新增一個空列,並賦一個標量值
frame['new'] = np.arange(5.) #新增一個空列,並賦一個標量值
- 將列表或陣列賦值給某個列時,其長度必須跟DataFrame 長度相匹配。如果是Series,會精確匹配DataFrame的索引,空位被缺失值填補。
Series = Series([1,2,3],index = ['one','two','three'])
frame['new'] = Series
- 構建DataFrame的方法②:巢狀字典(字典的字典)
- 如果將巢狀字典傳遞給DataFrame,它會被解釋為:外層字典的鍵作為列,內層鍵則作為行索引。
- 內層字典的鍵會被合併、排序以形成最終 的索引。除非顯式指定了索引。
- 可以輸入給DataFrame建構函式所能接受的各種資料
- 二維ndarray #資料矩陣,還可以傳入行標和列標。
- 由陣列、列表或元組組成的字典 #每個序列會變成DataFrame的一列,所有序列的長度必須相同。
- Numpy的結構化/記錄陣列 #類似於“由陣列組成的字典”
- 由Series組成的字典
- 由字典組成的字典
- 字典組成的Series列表
- 列表或元組組成的另一個DataFrame
- Numpy的MaskedAarry
- 如果設定了DataFrame的index和columns屬性,這些資訊會被現顯示出來。
- 跟Series一樣,values屬性也會以二維ndarray的形式返回DataFrame中的資料。
- 如果DataFrame各列的資料型別不同,則值陣列的資料型別會選用能夠相容所有列的資料型別。
3 索引物件
- pandas的索引物件負責管理軸標籤和其他元資料(比如軸名稱等)。構建Series或DataFrame時,所用到的任何陣列或其他序列的標籤會被轉換成一個index
- index物件不可修改。不可修改性非常重要,這樣才能使index物件在多個數據結構之間安全共享。
- index的功能也類似於一個固定大小的集合。
- 每個索引都有一些方法和屬性,可用於設定邏輯並回答有關該索引所包含的資料資訊的問題。
- index的方法和屬性:
- append # 連線另一個index物件,產生一個新的index
- diff # 計算差集,並得到一個index
- intersection # 計算交集
- union # 計算並集
- isin # 計算一個指示各值是否都包含在引數集合中的布林型陣列
- delete # 刪除索引i處的元素,並得到一個新的index
- drop # 刪除傳入的值,並得到新的index
- insert # 將元素插入到索引i處,並得到新的index
- is_monotonic # 當各元素均大於等於前一個元素時,返回True
- is_unique # 當index沒有重複值時,返回True
- unique # 計算index中唯一值得陣列
三 基本功能
1 重新索引
- pandas物件的一個重要方法是reindex,作用是建立一個適應新索引的新物件。根據新索引進行重排。
obj = Seires([],index = [])
obj = obj.reindex(['','',''])
obj = obj.reindex([],fillna = 0)
- reindex的mathod選項:
- ffill或pad # 前向填充值
- bfill或backfill # 後向填充值
- 對於DataFrame,reindex可以修改(行)索引、列,或兩個都修改。
frame = frame.reindex(['','','',''])
frame.reindex(columns = '')
frame.reindex(index = ['','','','',],method = 'ffill',columns = '')
- 利用ix的標籤索引功能,重新簡潔索引任務。
frame.ix[['','','',''],'']
- reindex函式的引數
- index # 用作索引的新序列,既可以是index例項,也可以是其他資料結構。index會被完全使用,就像沒有任何複製。
- method # 插值(填充)方式
- fill_value # 在重新索引的過程中,需要引用缺失值時使用的替代值。
- limit # 前向或後向填充時的最大填充量
- level # 在MultiIndex的指定級別上匹配簡單索引,否則選取其子集。
- copy # 預設為True,無論如何複製,如果為False,則新舊相等就不復制。
2 丟棄指定軸上的項
- 丟棄某條軸上的一個或多個項很簡單,只要有一個索引陣列或列表即可。由於需要執行一些資料整理和集合邏輯,所以drop方法返回的是一個在指定軸上刪除了指定值的新物件。
obj = Series(np.arange(5.),index = ['a','b','c','d','e','f'])
new_obj = obj.drop('c')
- 對於DataFrame,可以刪除任意軸上的索引值。
data.drop('one',axis = 0)
data.drop(['one','two'],axis = 1)
3 索引、選取、過濾
- Series索引的工作方式類似於Numpy陣列的索引,只不過Series的索引值不只是整數。
obj = Series(np.arange(5.),index = ['a','b','c','d','e','f'])
obj['b':'c']
obj['b':'c'] = 5
- 對DataFrame的索引其實就是獲取一個或多個列。
data['one']
data[['one','two']]
data[:2] #行切片索引選取
data[data['three'] > 5] #布林型陣列選取行
data < 5
data[data < 5] = 0
- 為了在DataFrame的行上進行標籤索引,引入專門的索引欄位ix,可以通過Numpy式的標記法以及軸標籤從DataFrame中選取行和列的子集,是一種重新索引的簡單手段。
data.ix['',['','']] #先行後列
data.ix[['',''],[1,0,3]] #先行後列
data.ix[[data.three > 5],[:2]]
- 對pandas物件中的資料的選取和重排方式有很多。在使用層次化索引時還能用到一些別的方法。
- DataFrame的索引選項
- obj.ix[:,val] # 選取單個列或列子集
- obj.ix[val1,val2] # 同時選取行和列
- reindex方法 # 將一個或多個軸匹配到新索引
- xs方法 # 根據標籤選取單行或單列,並返回一個Series
- icol、irow方法 # 根據整數位置選取單列或當行,並返回一個Seires
- get_value、set_value方法 # 根據行標籤和列標籤選取單個值。get_value是選取,set_value是設定。
4 算術運算和資料對齊
- pandas最重要的一個功能是,它可以對不同索引物件進行算術運算。在將物件相加時,如果存在不同的索引對,則結果的索引就是該索引對的並集。
- 自動的資料對齊操作在不重疊的索引處引入NA值,缺失值會在算術運算中廣播。
- 對於DataFrame,自動對齊會同時發生在行和列上。
1)在算術方法中填充值
- 在對不同索引的物件進行算術運算時,可能希望在一個物件中某個軸鏢旗南在另一個物件中找不到時填充一個特殊值(比如0)。
df1 + df2
df1.add(df2,fill_value = 0)
df1.reindex(columns = df2.columns,fill_value = 0)
- 靈活的算術方法
- add # +
- sub # -
- div # /
- mul # *
2)DataFrame和Series之間的運算
- 預設情況下,DataFrame和Series之間的算術運算會將Series的索引匹配到DataFrame的列,然後沿著行一直向下廣播。
5 函式應用和對映
- Numpy的ufuncs(元素級陣列方法)也可用於操作pandas物件。
- 將函式應用到由各列或行所形成的一維陣列上。DataFrame的apply方法可以實現此功能。
f = lambda x : x.max() - x.min()
frame.apply(f)
frame.apply(f,axis = 1)
- 元素級的Python函式也可以用。使用applymap函式可以得到frame中各個浮點值的格式化字串。
format = lambda x : '%.2f' %x
frame.applymap(format)
- Series有一個應用於元素級函式的map方法。
frame['e'].map(format)
6 排序和排名
1)排序
- 按條件對資料集排序(sorting)是一種重要的內建運算。對行或列索引排序,可使用sort_index方法,返回一個已排序的新物件。
frame.sort_index()
frame.sort_idnex(axis = 1) #根據任意軸上的索引就行排序
frame.sort_index(axis = 1,ascending = False) #資料預設是按升序排序的,也可設定降序排序。
- 對於Series,若按值進行排序,可使用其order方法:obj.order()
- 在排序時,任何缺失值預設都會被放到Series的末尾。
- 對於DataFrame,通過將一個或多個列的名字傳遞給by選項可對一個或多個列進行排序。
frame.sort_index(by = 'a')
frame.sort_index(by = ['a','b'])
2)排名
- 排名(ranking)跟排序關係密切,且它會增設一個排名值(從1開始,一直到陣列中有效資料的數量)。與numpy.argsort間接排序索引差不多,只不過可以通過某種規則破壞平級關係。
- rank方法通過“為各組分配一個平均排名”的方式破壞平級關係
- obj.rank() # 直接排名
- obj.rank(method = ‘first’) # 根據值在原資料中出現的順序給出排名
- obj,rank(ascendiing = False, method = ‘max’) # 降序排名
- 排名時用於破壞平級關係的method選項:
- ‘average’ # 在相等分組中,為各個值分配平均排名
- min # 使用整個分組的最小排名
- max # 使用整個分組的最小排名
- first # 按值在原資料中的出現順序排名
7 帶有重複值的軸索引
- 雖然pandas函式如(reindex)等都要求標籤唯一,但這並不強制。
- 索引的is_unique屬性可以顯示索引對應的值是否唯一。
- 對於重複值得索引,資料選擇返回的結果不同。如果索引對應單個值,返回標量值;如果索引對應多個值,返回一個Series。
四 彙總和計算描述統計
- pandas物件擁有一組常用的數學和統計方法。大部分都屬於約簡和彙總統計,用於從Series中提取單個值(sum or mean)或從DataFrame的行或列中提取一個Series。與對應的Numpy陣列方法相比,它們都是基於沒有缺失資料的假設構建的。
- 約簡方法的選項:
- ① axis # 約簡的軸,DataFrame的行用0,列用1
- ② skipna # 排除缺失值,預設值為True
- ③ level # 如果軸是層次化索引的(MultiIndex),則更具level分組簡約
- 描述和彙總統計
- count # 非NA值得數量
- describe # 彙總統計描述
- min、max # 最小值和最大值
- argmin、argmax # 最小值和最大值的索引位置
- idximin、idxmax # 最小值和最大值的索引值
- quantile # 樣本分位數
- sum # 總和
- mean # 平均數
- median # 算術中位數
- mad # 根據平均值計算平均絕對誤差
- var # 方差
- std # 標準差
- skew # 偏度(三階矩)
- kurt # 峰度(四階距)
- cumsum # 累計和
- cummin、cummax # 累計最小值和累計最大值
- cumprod # 累計積
- diff # 一階分差(對時間序列很有用)
- pct_change #百分比變化
1 相關係數與協方差
- 有些彙總統計(如相關係數和協方差) 是通過引數計算出來的。
- Series的corr方法用於計算兩個Series中重疊的、非NA的、按索引對齊的值得相關係數。cov用於計算協方差。
- DataFrame的corr和cov方法將以DataFrame的形式返回完整的相關係數和協方差矩陣。
- 利用DataFrame的corrwith方法,可以計算列或行與另一個Series或DataFrame之間的相關係數。
2 唯一值、值計數、成員資格
1)唯一值
uniques = obj.unique()
uniques.sort() # 對結果進行排序
2)值計數
- Series是按值頻率降序排列的。
- value_counts是一個頂級pandas方法 ,可用於任何陣列或序列。
pd.value_counts(obj.values,sort = Flase)
data = df.apply(pd.value_counts).fillna(0)
3)成員資格
- isin,用於判斷向量化集合的成員資格
五 處理缺失資料
- 缺失資料(missing data)在大部分資料分析中都很常見。pandas的設計目標之一就是讓缺失資料的處理任務儘量輕鬆。
- pandas物件上的所有描述統計都排除了缺失資料。
- pandas使用浮點值(Not a Number)表示浮點和非浮點陣列中的缺失資料,只是一個便於被檢測出來的標記。
- python內建的None也會表當作NaN處理。
- NA處理方法
- dropna # 根據各標籤的值是否存在缺失資料對軸標籤進行過濾,可通過閾值調節對缺失值的容忍度。
- fillna # 用指定值或者插值(ffill或bfill)填充缺失資料。
- isnull # 返回一個布林型物件
- notnull # isnull的否定形式
1 濾除缺失資料
- 對於Series,dropna返回一個僅含非空資料和索引值的Series
data.dropna()
data[data.notnull()]
- DataFrame,稍微複雜一點,dropna預設丟棄任何含有缺失值的行,也可設定丟棄全NA或含有NA的行或列。
data.dropna(how = 'all') #傳入how = 'all'將只丟棄全為NA的那些行
data.dropna(axis = 1,how = 'all') #丟棄列
- 另一個濾除DataFrame行的問題設計時間序列處理。若只想留下一部分觀測資料,可以用thresh引數。
df.dropna(thresh = 3)
2 填充缺失資料
- fillna方法主要用於填補缺失資料。
- 填充常數值
- 通過一個字典數呼叫fillna,對不同的列填充不同的值。
- fillna預設返回新物件,但也可以對現有物件進行就地修改。
data = df.fillna(0,inplace = True)
- 對reindex有效的插值方法也可以用於fillna。
df.fillna(method = 'ffill')
df.fillna(method = 'ffill',limit = 2)
- fillna也可以傳入Series的平均數或中位數。
data.fillna(data.mean())
- fillna函式引數說明:
- ① value # 用於填充缺失值的標量值或字典物件
- ② method # 插值方式。如果未函式呼叫時未指定其他引數,預設為’ffill’
- ③ axis # 待填充的軸,預設axis = 0
- ④ inpalce # 修改呼叫者物件而不產生副本
- ⑤ limit # (對於向前和向後填充)可以連續填充的最大數量
六 層次化索引
- 層次化索引(hierarchical indexing)是pandas的一項重要功能,它使你能夠在軸上有用多個(兩個以上)索引級別。抽象點說,它使你能以低維度形式處理高維度資料。
data = Series(np.random.randn(10),index = [['a','a','a','b','b','b','b','c','c','c'],[1,2,3,1,2,3,1,2,3]])
- 這就是帶有MultiIndex索引的Series的格式化輸出形式。索引之間的“間隔”表示“直接使用上面的標籤”。
- 對於一個層次化索引的物件,選取資料子集的操作很簡單:
data['b'] #直接索引
data['b':'c'] # 切片索引
data[:,2] # 內層中選取
- 層次化索引在資料重塑和基於分組的操作(如透視表生成)中扮演著重要的角色。比如:unstack方法和其逆運算stack方法:
data.unstack()
data.unstack().stack()
- 對於一個DataFrame,每條軸都可以有分層索引,每層都可以有名字(可以是字串,也可以是其他Python物件),如果指定了名稱,它們就會顯示在控制檯輸出中。(不要將索引名稱跟軸標籤混為一談)
frame.index.name = ['key1','key2']
frame.columns.names = ['state,'color']
- 由於有了分部索引,因此可以輕鬆選取列分組。
1 重排分級順序
- 有時,需要重新調整某條軸上各級別的順序,或根據指定級別上的值對資料進行排序。swaplevel接受兩個級別編號或名稱,並返回一個互換了級別的新物件(資料不會發生變化)。
frame.swaplevel('key1','key2')
- sortlevel則根據單個級別中的值對資料進行排序(穩定的)。交換級別時,常常也會用到sortlevel,這樣最終結果就有序了。
frame.sortlevel(1)
frame.swaplevel(0,1).sortlevel(0)
- 在層次化索引的物件上,如果索引是按字典方式從外到內排序,即呼叫sortlevel(0)或sort_index()的結果,資料選取操作的效能會好很多。
2 根據級別彙總統計
- 許多對DataFrame和Series的描述和彙總統計都有一個level選項,它用於指定在某條軸上求和的級別。類似pandas的groupby功能。
3 使用DataFrame的列
- 很多情況下,DataFrame的一個或多個列可以當做索引來用,或者將索引轉變為DataFrame的列。
- DataFrame 的set_index函式會將其一個或多個列轉換為行索引,並建立一個新的DataFrame。
- 預設情況下,這些被轉換為索引的列會被刪除,也可以調參保留。
frame2 = frame.set_index(['c','d'])
frame.set_index(['c','d'],drop = Flase)
- reset_index的功能與set_index剛好相反,層次化索引的級別會被轉移到列裡面。
frame.reset_index()
七 其他有關pandas的話題
1 整數索引
- 基於標籤或位置的索引
- 為了保持良好的一致性。如果軸索引含有索引器,那麼根據整數進行資料選取的操作將總是面向標籤,也包括用ix進行切片。
- 如果需要可靠的、不考慮索引型別的、基於位置的索引,可以用Series的iget_value方法和DataFrame的irow和iloc方法。
serie.iget_value()
frame.irow()
2 面板資料
pandas有一個panel資料結構,可以看做一個三維版的DataFrame,pandas大部分開發工作都集中在表格型資料的操作上,層次化索引頁使得多數情況下不需要用到N維陣列。
stacked = pdata.ix[:].to_frame() # panel的資料呈現形式
stacked.to_panel()