最后一次更新日期: 2019/4/20
pandas
是基于numpy
的數據分析庫,提供一些更易用的數據模型和大量高效的統計方法。
使用前先導入模塊:
import pandas as pd
按需導入以下模塊:
import numpy as np
import matplotlib.pyplot as plt
此篇為匯總,點擊下方鏈接可前往各小節
簡要使用教程1 - 數據模型與屬性 (索引,數據序列,數據框,分類數據)
簡要使用教程2 - 數據類型與轉換 (數據類型,類型轉換)
簡要使用教程3 - 數組與統計運算 (運算符和標量值函數,統計方法,自定義函數,廣播)
簡要使用教程4 - 查詢與關聯 (索引查找,表連接)
簡要使用教程5 - 增刪改 (更新,增加,刪除,重構索引,行列轉置,缺失值填充)
簡要使用教程6 - 排序與去重 (直接與間接排序,去重)
簡要使用教程7 - 亂序與抽樣 (隨機排序,抽樣)
簡要使用教程8 - 讀寫 (讀寫csv,讀寫excel,讀寫sql)
簡要使用教程9 - 快速繪圖 (曲線圖,條形圖,直方圖,箱線圖,散點圖,餅圖)
也可以看看:
numpy使用指南
matplotlib簡要使用教程
一. 數據模型與屬性
1. 索引Index
numpy中只有位置索引,而pandas還增加了標簽索引,依賴于一個專用的Index
類型。
常規索引
In [64]: pd.Index([1,2,3])
Out[64]: Int64Index([1, 2, 3], dtype='int64')
In [65]: pd.Index([1.,2.,3.])
Out[65]: Float64Index([1.0, 2.0, 3.0], dtype='float64')
In [66]: pd.Index(['a','b','c'])
Out[66]: Index(['a', 'b', 'c'], dtype='object')
In [67]: pd.Index(range(10))
Out[67]: RangeIndex(start=0, stop=10, step=1)
In [68]: pd.Index(range(10)).values
Out[68]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int64)
In [80]: import datetime as dt
...: dt1=dt.datetime.now()
...: dt2=dt1+dt.timedelta(days=1)
In [81]: pd.Index([dt1,dt2])
Out[81]: DatetimeIndex(['2019-03-09 20:56:14.644159', '2019-03-10 20:56:14.644159'], dtype='datetime64[ns]', freq=None)
Index
在創建時會根據傳入數據(一維序列)自動生成具體的索引類型,也可通過dtype
參數指定類型,但無法正常轉換時會報錯;copy
參數指定創建索引時是否復制源數據,默認false
。
具體的索引類型也可通過各自的方法創建。
Index.values
可以查看作為數據基礎的一維數組,Index.dtype
可以查看數據類型。
多級索引
pandas提供了多級索引以便于分組數據,可用于構造高維數據集,groupby
計算也會自動產生多級索引。
In [5]: midx=pd.MultiIndex(levels=[['a','b'],['c','d']],labels=[[1,1,0,0],[0,1,0,1]],name=['idx1','idx2'])
In [6]: midx
Out[6]:
MultiIndex(levels=[['a', 'b'], ['c', 'd']],
labels=[[1, 1, 0, 0], [0, 1, 0, 1]],
names=['idx1', 'idx2'])
In [9]: midx.set_labels([1,0,1,0],level=1)
Out[9]:
MultiIndex(levels=[['a', 'b'], ['c', 'd']],
labels=[[1, 1, 0, 0], [1, 0, 1, 0]],
names=['idx1', 'idx2'])
In [11]: midx.swaplevel(0,1)
Out[11]:
MultiIndex(levels=[['c', 'd'], ['a', 'b']],
labels=[[0, 1, 0, 1], [1, 1, 0, 0]],
names=['idx2', 'idx1'])
In [12]: pd.MultiIndex.from_arrays([['a','a','b','b'],['c','d','c','d']],names=['idx1','idx2'])
Out[12]:
MultiIndex(levels=[['a', 'b'], ['c', 'd']],
labels=[[0, 0, 1, 1], [0, 1, 0, 1]],
names=['idx1', 'idx2'])
MultiIndex
的第一個參數levels
是每個級別的唯一標簽列表,是一個兩層嵌套的序列,外層對應級別,內層對應唯一標簽;
第二個參數labels
是所有記錄在每個級別上選取的標簽序號,也是一個兩層嵌套的序列,外層對應級別,內層對應記錄,新版本中已被codes
參數取代;
第四個參數names
是每個級別的名稱。
MultiIndex
提供了一些輔助方法,set_levels
、set_labels
、set_names
可以設置整體或是某一級別的索引屬性,通過level
參數指定級別,默認設置整體;
swaplevel
可以交換級別,droplevel
可以刪除級別,sortlevel
可以對指定級別排序;
from_array
、from_tuples
、from_product
、from_frame
方法可從其他結構的數據中創建索引。
2. 數據序列Series
In [99]: s=pd.Series([1,2,3,4],name='s1')
In [100]: s
Out[100]:
0 1
1 2
2 3
3 4
Name: s1, dtype: int64
In [101]: pd.Series([[1,2],[3,4]],index=['row1','row2'])
Out[101]:
row1 [1, 2]
row2 [3, 4]
dtype: object
In [102]: s.dtype
Out[102]: dtype('int64')
In [103]: s.name
Out[103]: 's1'
In [104]: s.values
Out[104]: array([1, 2, 3, 4], dtype=int64)
In [105]: s.index
Out[105]: RangeIndex(start=0, stop=4, step=1)
In [106]: s.shape
Out[106]: (4,)
核心數據模型其一,由序列名name
、標簽索引index
、值數組(一維)values
組成。用于存放一維數據,只有一個軸方向:0,shape
屬性可以查看數據集的形狀。
創建時只能接收一維序列數據(list,tuple,ndarray),超過一維的將后面的維度看作元素的維度,會根據傳入的數據自動判斷類型,也可通過dtype
參數顯示指定。
默認情況下會生成范圍索引,可通過index
參數指定一個一維序列作為索引,也可在創建后直接為index
屬性賦值。
3. 數據框DataFrame
In [107]: df=pd.DataFrame([[1,'a'],[2,'b']],columns=['col1','col2'])
In [108]: df
Out[108]:
col1 col2
0 1 a
1 2 b
In [113]: df.dtypes
Out[113]:
col1 int64
col2 object
dtype: object
In [114]: df.index
Out[114]: Int64Index([1, 2], dtype='int64', name='col1')
In [116]: df.columns
Out[116]: Index(['col1', 'col2'], dtype='object')
In [117]: df.values
Out[117]:
array([[1, 'a'],
[2, 'b']], dtype=object)
In [125]: df.col2
Out[125]:
col1
1 a
2 b
Name: col2, dtype: object
In [126]: pd.DataFrame({'col1':[1,3],'col2':['a','b']})
Out[126]:
col1 col2
0 1 a
1 3 b
In [127]: df.shape
Out[127]: (2, 2)
核心數據模型其二,也就是數據表,由列標簽索引columns
、行標簽索引index
、值數組(二維)values
組成。用于存放二維數據,有兩個軸方向:0和1,對應行坐標和列坐標,shape
屬性可以查看數據集的形狀。列數據的訪問可以通過與列名相同的屬性名訪問,僅在定義了字符串列名時可用,一個單列即是一個Series
。
創建時只能接收二維序列數據(list,tuple,ndarray),超過二維的將后面的維度看作元素的維度,會根據傳入的數據自動判斷類型,也可通過dtype
參數顯示指定,與numpy不太一樣的是,DataFrame
的列可以定義不同的數據類型,通過創建時的自動判斷,或是篩選出列后轉換類型,DataFrame.dtypes
屬性可查看所有列的數據類型。相比numpy,pandas的DataFrame
創建還增加了對dict
數據源的支持,key
對應列名,value
對應列數據。
默認情況下會生成范圍索引,可通過index
參數指定一個一維序列作為索引,也可在創建后直接為index
屬性賦值,DataFrame.set_index
方法可以返回替換了索引的數據框副本而不影響原數據。
DataFrame
相當于Series
的堆疊,沿DataFrame
的行或列方向進行寬度為1的切片,得到的就是一個Series
。
原本pandas還提供了三維的數據模型Panel
,但新版中已經廢棄,可嘗試使用多級索引MultiIndex
來構造更高維度的數據集。
4. 分類數據Categorical
pandas提供了分類數據類型用于約束此類數據,該類型會限制分類標簽的取值,并可為分類標簽提供排序依據。
In[14]: pd.Categorical(['a','b','b','c'],categories=['a','b'],ordered=True)
Out[14]:
[a, b, b, NaN]
Categories (2, object): [a < b]
In[15]: pd.Categorical(['a','b','b','c'])
Out[15]:
[a, b, b, c]
Categories (3, object): [a, b, c]
第一個參數values
為所有分類標簽的序列;
第二個參數categories
為唯一分類標簽的序列,當指定該參數后,values
中不屬于categories
的標簽會被替換為NaN
,不指定時會根據values
自動生成;
第三個參數ordered
聲明唯一分類標簽是否指示排序方式,為True
時會按categories
中的順序對標簽標定大小關系,默認False
。
二. 數據類型與轉換
1. 數據類型
pandas支持的數據類型就是numpy的數據類型,在創建數據模型時同樣可通過dtype
參數指定。
常用的數據類型有:np.bool_
(bool),np.int64
(int),np.float64
(float),np.datetime64
(datetime),object
(str等),pd.Categorical
(category)。
更詳細的類型說明可查看numpy的使用指南。
和numpy不太一樣的是,numpy中int
類型默認為np.int32
,而pandas中默認np.int64
;numpy中存儲字符串優先采用定長的np.str_
,而pandas中統一使用object
。
pandas數據模型使用單個ndarray
作為基礎數據,所以當pandas的每列采用不同數據類型時,作為數據來源的ndarray
整體被設置為object
數據類型。
2. 類型轉換
In [48]: df=pd.DataFrame([[1,'2'],[3,'a']],columns=['col1','col2'])
In [49]: df.dtypes
Out[49]:
col1 int64
col2 object
dtype: object
In [50]: df.col1.astype('float')
Out[50]:
0 1.0
1 3.0
Name: col1, dtype: float64
In [52]: pd.to_numeric(df.col2,errors='ignore')
Out[52]:
0 2
1 a
Name: col2, dtype: object
In [53]: pd.to_numeric(df.col2,errors='coerce')
Out[53]:
0 2.0
1 NaN
Name: col2, dtype: float64
pandas和numpy一樣主要使用astype
進行類型轉換,該方法返回轉換后數據,需要在原數據上更改時可以用返回值去覆蓋原數據。
當需要進行一些可能會失敗的轉換時,可以考慮使用專用的方法,例如pd.to_numeric
用于將一個Series
轉換為數字類型,errors
參數可以指定對錯誤的處理方式:'coerce'
表示強制轉換,不能轉換的元素會替換為NaN
;'ignore'
表示存在無法轉換的元素時會放棄轉換。
當需要對DataFrame
整體應用轉換時,可使用apply
方法。
三. 數組與統計運算
1. 運算符和標量值函數
pandas重載了python的大部分運算符,可以直接進行數組計算,numpy的標量值函數也可直接使用,這些運算都是將原本作用于單個元素的運算拓展到整個數組。
In [56]: df=pd.DataFrame([[1,'2'],[3,'a']],columns=['col1','col2'])
In [57]: df+df
Out[57]:
col1 col2
0 2 22
1 6 aa
In [201]: np.sqrt(df.col1)
Out[201]:
0 1.000000
1 1.732051
Name: col1, dtype: float64
使用的運算符和函數必須對參與運算的所有數據類型都是有意義的,否則會報錯。
匹配方式
In [154]: s1=pd.Series([1,2,3,4],index=[0,1,2,3])
In [155]: s2=pd.Series([5,6,7,8],index=[1,2,3,4])
In [156]: s1+s2
Out[156]:
0 NaN
1 7.0
2 9.0
3 11.0
4 NaN
dtype: float64
此處需要注意pandas和numpy的區別,pandas的數組運算在元素匹配上是基于標簽索引的,未能匹配到的位置會被替換為NaN,numpy則是基于位置索引。
2. 統計方法
聚合函數
pandas繼承了numpy的聚合函數:sum
、mean
、max
、min
等。
可通過Series
和DataFrame
的方法調用,或是調用numpy下的靜態方法。
In [58]: df.sum()
Out[58]:
col1 4
col2 2a
dtype: object
In [60]: np.max(df)
Out[60]:
col1 3
col2 a
dtype: object
In [114]: df.agg({'col1':'max','col2':'sum'})
Out[114]:
col1 3
col2 2a
dtype: object
In [115]: df.agg(['max','sum'])
Out[115]:
col1 col2
max 3 a
sum 4 2a
通過pandas數據模型的方法調用時,
第一個參數axis
可以指定統計的軸,Series
指定該參數沒有意義,DataFrame
默認沿軸0統計,即按列統計。pandas無法指定對所有軸展開統計,如有需要可以使用numpy的方法;
第二個參數skipna
可以指示是否跳過NaN
值;
第三個參數level
用于在存在多級索引的情況下指定某一級索引進行統計;
第四個參數numeric_only
用于指定是否只對數字應用計算。
當對DataFrame
沿行方向統計時,由于不同列的數據類型可能不一樣,需保證對應運算是有意義的,否則無法得到期望的結果。
agg
方法是aggregate
方法的簡寫,用于對不同列應用不同聚合函數或是多種聚合函數,可以傳入list
或是dict
聲明統計方式。
分組統計
pandas提供了類似于sql的groupby
方法用于分組統計。
In [88]: df=pd.DataFrame([['a','c',1],['a','d',2],['b','d',3]],columns=['col1','col2','col3'])
In [89]: df
Out[89]:
col1 col2 col3
0 a c 1
1 a d 2
2 b d 3
In [93]: result=df.groupby(by=['col1','col2']).agg(['max','min'])
In [94]: result
Out[94]:
col3
max min
col1 col2
a c 1 1
d 2 2
b d 3 3
In [95]: result.sum(level=0)
Out[95]:
col3
max min
col1
a 3 3
b 3 3
In [140]: gb=df.groupby(by=['col1','col2'])
In [141]: gb.groups
Out[141]:
{('a', 'c'): Int64Index([0], dtype='int64'),
('a', 'd'): Int64Index([1], dtype='int64'),
('b', 'd'): Int64Index([2], dtype='int64')}
In [142]: gb.get_group(('a','c'))
Out[142]:
col1 col2 col3
0 a c 1
只調用groupby
方法會得到一個DataFrameGroupBy
對象,通過其groups
方法可查看所有分組信息,get_group
方法可獲取指定分組。
該對象可調用各種聚合函數,或調用agg
方法進行復合的聚合統計,返回包含多級索引的DataFrame
統計結果表,對于結果表,可以繼續應用統計函數并通過level
參數指定索引級別進行二次統計。
3. 應用自定義函數
除pandas和numpy提供的函數外,還可以自定義函數并使用apply
、applymap
、map
方法快速應用于整個數據集。
In [119]: df.apply(lambda x: x.col1+x.col2, axis=1)
Out[119]:
0 3
1 7
dtype: int64
In [120]: def add(row):
...: return row.col1+row.col2
In [121]: df.apply(add, axis=1)
Out[121]:
0 3
1 7
dtype: int64
In [122]: df.applymap(lambda x: x*2)
Out[122]:
col1 col2
0 2 4
1 6 8
In [123]: def double(item):
...: return item*2
In [124]: df.applymap(double)
Out[124]:
col1 col2
0 2 4
1 6 8
In [128]: s=pd.Series(['a','b','b'])
In [129]: s.map(lambda x: x*2)
Out[129]:
0 aa
1 bb
2 bb
dtype: object
In [130]: s.map({'a':'c','b':'d'})
Out[130]:
0 c
1 d
2 d
dtype: object
DataFrame
有apply
和applymap
兩個方法:
apply
將函數應用于每行或者每列,axis
參數指定應用函數的軸方向,值為0表示按列應用,即逐列作為函數的參數進行計算,值為1表示按行應用,默認為0;
applymap
將函數應用于每個元素。
Series
只有一個map
方法,用于將函數應用于元素,除此以外,還提供值映射的功能,輸入dict
類型時會根據key-value映射將相應的值替換。
支持lambda匿名函數。
4. 廣播
In [80]: l2=[1,2]
...: a2=np.array(l2)
...: s2=pd.Series(l2)
...: df21=pd.DataFrame([1,2])
...: df12=pd.DataFrame([[1,2]])
...: l22=[[1,2],[3,4]]
...: a22=np.array(l22)
...: df22=pd.DataFrame(l22)
...: df23=pd.DataFrame([[3,4,5],[6,7,8]])
In [99]: df22+l2
Out[99]:
0 1
0 2 4
1 4 6
In [100]: df22+a2
Out[100]:
0 1
0 2 4
1 4 6
In [101]: df22+s2
Out[101]:
0 1
0 2 4
1 4 6
In [102]: df22+df21
Out[102]:
0 1
0 2 NaN
1 5 NaN
In [103]: df22+df12
Out[103]:
0 1
0 2.0 4.0
1 NaN NaN
In [104]: df23+s2
Out[104]:
0 1 2
0 4.0 6.0 NaN
1 7.0 9.0 NaN
In [130]: df21+df12
Out[130]:
0 1
0 2.0 NaN
1 NaN NaN
pandas的廣播機制繼承自numpy但有不一樣的地方:
標量值會與DataFrame
或Series
中每個元素進行同樣的計算;
Series
或一維list
或一維ndarray
會與DataFrame
的每一行進行運算,Series
在長度不足以匹配DataFrame
的行時不足部分會替換為NaN
,其他兩種長度不足會報錯;
DataFrame
與DataFrame
進行運算會按元素匹配,無論行列,長度不足的部分都會替換為NaN
;
二維ndarray
與DataFrame
的運算遵循numpy的廣播規則,長度不足且為1的軸會被廣播至同等大小;
二維list
與DataFrame
的運算不被支持。
四. 查詢和關聯
1. 索引查找
(1). 索引器格式
單值選取:[value,...]
多值選取:[[value1,value2],...]
范圍選取:[start:end:step,...]
start
表示區間的開始,默認值0,end
表示區間的結束(不包含),默認值等于軸長度,step
表示選取的步長,默認值1,采用默認值的參數可以省略,[:,...]
表示對應軸方向上全部選取。
pandas中索引器的格式與numpy差不多,但用法有區別。pandas除了numpy的位置索引,還增加了標簽索引,雖然可以對Series
和DataFrame
直接使用索引器,但用法被嚴格限制,建議改用iloc
和loc
方法進行索引。
(2). 直接索引
In [157]: df=pd.DataFrame(np.arange(1,10).reshape((3,3)),columns=['col1','col2','col3'],index=['row1','row2','row3'])
In [158]: df[0:3:2]
Out[158]:
col1 col2 col3
row1 1 2 3
row3 7 8 9
In [161]: df['row1':'row3':2]
Out[161]:
col1 col2 col3
row1 1 2 3
row3 7 8 9
In [162]: df['col2']
Out[162]:
row1 2
row2 5
row3 8
Name: col2, dtype: int32
In [163]: df[['col1','col3']]
Out[163]:
col1 col3
row1 1 3
row2 4 6
row3 7 9
In [168]: df['col2'][1:3]
Out[168]:
row2 5
row3 8
Name: col2, dtype: int32
直接索引提供了有限的幾種使用方式:按行位置進行索引切片、按行標簽進行索引切片、按列標簽取列、按列標簽列表取多列、布爾索引篩選行、索爾索引篩選元素等。
一次索引器只能使用一種方式,不能行列同時操作,如有需要,可進行連續索引。
(3). loc和iloc索引
In [169]: df.loc['row1','col1']
Out[169]: 1
In [170]: df.loc['row1':'row3':2,'col1':'col3':2]
Out[170]:
col1 col3
row1 1 3
row3 7 9
In [185]: df.iloc[0,0]
Out[185]: 1
In [186]: df.iloc[0:3:2,0:3:2]
Out[186]:
col1 col3
row1 1 3
row3 7 9
loc
專用于標簽索引,iloc
專用于位置索引,索引器可接收單值、列表、范圍、布爾索引,可同時索引行和列。
(4). 布爾索引
In [190]: df>5
Out[190]:
col1 col2 col3
row1 False False False
row2 False False True
row3 True True True
In [191]: df[df>5]
Out[191]:
col1 col2 col3
row1 NaN NaN NaN
row2 NaN NaN 6.0
row3 7.0 8.0 9.0
In [192]: df['col1']>2
Out[192]:
row1 False
row2 True
row3 True
Name: col1, dtype: bool
In [193]: df.loc[df['col1']>2]
Out[193]:
col1 col2 col3
row2 4 5 6
row3 7 8 9
In [196]: df.loc[df['col1']>2,df.iloc[1]>5]
Out[196]:
col3
row2 6
row3 9
In [208]: df.iloc[df['col1'].values>2]
Out[208]:
col1 col2 col3
row2 4 5 6
row3 7 8 9
布爾索引是一種比較特殊的索引,通過對pandas或numpy的數據模型進行邏輯運算得到,與源數據結構相同,數據類型為bool
,用于標識每個元素是否符合邏輯運算的條件。在索引器中使用布爾索引可以篩選出符合條件的數據。
在直接索引時,二維布爾索引可以用于篩選DataFrame
的元素,形狀不變,不符合條件的元素會被替換為NaN
,這一點和numpy不一樣,numpy進行同樣形式的篩選時會將符合條件的元素構造為新的一維數組返回;一維布爾索引只可以用于篩選行數據;
在使用loc
索引時,不能使用二維布爾索引,只能針對每個軸使用一維布爾索引,并且必須是由Series
運算得到的帶有標簽索引的布爾索引;
在使用iloc
索引時,同樣不能使用二維布爾索引,只能針對每個軸使用一維布爾索引,并且必須是由一維ndarray
運算得到的不含標簽索引的布爾索引(Series.values
可得到對應的ndarray
)。
(5). 指定值查找
In [141]: df=pd.DataFrame({'a':[np.nan,1,2],'b':[3,np.nan,4]})
In [142]: df
Out[142]:
a b
0 NaN 3.0
1 1.0 NaN
2 2.0 4.0
In [143]: df.isin([2,3])
Out[143]:
a b
0 False True
1 False False
2 True False
In [144]: df.isna()
Out[144]:
a b
0 True False
1 False True
2 False False
isin
方法用于查找存在于指定列表中的值,isna
方法用于查找NaN值,兩方法都會返回布爾索引,通常結合索引器使用。
2. 表連接
pandas提供了類似于sql的join
、merge
、concat
方法進行表連接。
(1). 索引連接
In [227]: df1=pd.DataFrame([[1,2],[3,4]],columns=['col1','col2'],index=[1,0])
In [228]: df2=pd.DataFrame([[5,6],[7,8]],columns=['col3','col4'],index=[0,1])
In [229]: df1.join(df2,how='inner')
Out[229]:
col1 col2 col3 col4
1 1 2 7 8
0 3 4 5 6
join
方法根據索引進行表連接,how
參數指定連接方式,有inner
內連接、outer
外連接、left
左連接、right
右連接 這幾種,默認為left
。
此處的join
和sql中的join并不一樣。
(2). 鍵連接
In [233]: df1=pd.DataFrame({'col1':[1,2,3],'col2':[4,5,6]})
In [234]: df2=pd.DataFrame({'col2':[4,5,7],'col3':[1,2,2]})
In [235]: df1.merge(df2)
Out[235]:
col1 col2 col3
0 1 4 1
1 2 5 2
In [237]: df1.merge(df2,how='left',left_on='col1',right_on='col3')
Out[237]:
col1 col2_x col2_y col3
0 1 4 4.0 1.0
1 2 5 5.0 2.0
2 2 5 7.0 2.0
3 3 6 NaN NaN
merge
方法根據指定鍵(列)進行表連接,通過on
參數(相同鍵)或left_on
和right_on
參數(不同鍵)指定,默認會將兩表中都存在的鍵作為連接鍵;how
參數指定連接方式,有inner
內連接、outer
外連接、left
左連接、right
右連接 這幾種,默認為inner
。
該方法才是sql中join的等效方法。
(3). 拼接
In [239]: df1=pd.DataFrame({'col1':[1,2,3],'col2':[4,5,6]})
In [240]: df2=pd.DataFrame({'col2':[4,5,7],'col3':[1,2,2]})
In [241]: pd.concat([df1,df2])
Out[241]:
col1 col2 col3
0 1.0 4 NaN
1 2.0 5 NaN
2 3.0 6 NaN
0 NaN 4 1.0
1 NaN 5 2.0
2 NaN 7 2.0
In [242]: pd.concat([df1,df2],join='inner')
Out[242]:
col2
0 4
1 5
2 6
0 4
1 5
2 7
In [243]: pd.concat([df1,df2],axis=1)
Out[243]:
col1 col2 col2 col3
0 1 4 4 1
1 2 5 5 2
2 3 6 7 2
用于拼接表,等效于sql中的union all。
axis
參數指定用于拼接的軸,默認0;join
參數指定其他軸的處理方式,inner
表示只返回都存在的項,outer
表示全部返回,默認outer
。
拼接后的結果表中可能會有行索引或列索引上的重復,可以視需要重整索引。
五. 增刪改
1. 更新
In [259]: df=pd.DataFrame({'a':[1,2],'b':[3,4]})
In [260]: df.iloc[0,0]=0
In [261]: df[df>2]+=1
In [262]: df
Out[262]:
a b
0 0 4
1 2 5
In [265]: df['a']=[2,1]
In [266]: df
Out[266]:
a b
0 2 4
1 1 5
In [268]: df[:]=[1,2]
In [269]: df
Out[269]:
a b
0 1 2
1 1 2
更新數據的方式與numpy一樣,索引篩選數據后直接賦值就行了,可以對所有元素賦值同一個標量,也可賦值同樣形狀的數據集,或是對DataFrame
每行賦值同樣的數據序列。
2. 增加
In [246]: df=pd.DataFrame({'a':[1,2],'b':[3,4]})
In [247]: df['c']=[5,6]
In [248]: df
Out[248]:
a b c
0 1 3 5
1 2 4 6
In [252]: df.loc[2]=-1
In [253]: df
Out[253]:
a b c
0 1 3 5
1 2 4 6
2 -1 -1 -1
In [254]: df.insert(0,'new',[0,0,0])
In [255]: df
Out[255]:
new a b c
0 0 1 3 5
1 0 2 4 6
2 0 -1 -1 -1
借助索引器可直接為新行或是新列賦值。
insert
方法可以在指定位置插入新列,loc
參數指定位置索引,column
參數指定列名,value
指定新列的數據。
3. 刪除
In [276]: df=pd.DataFrame({'a':[1,2,3],'b':[4,5,6]})
In [277]: df[df['a']>2]
Out[277]:
a b
2 3 6
In [281]: df.drop([0,2])
Out[281]:
a b
1 2 5
In [282]: df.drop('a',axis=1)
Out[282]:
b
0 4
1 5
2 6
刪除數據最靈活的方法就是通過索引篩去不需要的數據。
也可通過drop
刪除指定索引標簽的數據,labels
指定要刪除的標簽,可以是標量或是列表,axis
參數指定查找索引標簽的軸,默認為0。該方法是根據索引標簽而不是位置去刪除的,所以如果指定標簽存在重復,這些數據會一起被刪除。
4. 重構索引
In [246]: df=pd.DataFrame({'a':[1,2],'b':[3,4]})
In [256]: df.reindex(columns=['a','b','c','d'],fill_value=0)
Out[256]:
a b c d
0 1 3 0 0
1 2 4 0 0
reindex
方法用于重構索引,可以實現復雜的結構變更,包括行列的增加、刪除、移位,index
設置新的行索引,columns
參數設置新的列索引,已存在的索引會和數據一起被移至新的位置,不存在的將被創建,fill_value
參數可以指定新增行列的填充值。
5. 行列轉置
In [133]: df=pd.DataFrame({'a':[1,2],'b':[3,4]})
In [134]: df
Out[134]:
a b
0 1 3
1 2 4
In [135]: df.T
Out[135]:
0 1
a 1 2
b 3 4
DataFrame.T
用于實現行列轉置,整個數據集將沿左上至右下的對角線翻轉。
Series
調用轉置方法是無效的,如果需要轉置,先調用to_frame
方法轉為DataFrame
。
6. 缺失值填充
In [95]: df=pd.DataFrame({'a':[np.nan,1,3],'b':[2,np.nan,6]})
In [96]: df
Out[96]:
a b
0 NaN 2.0
1 1.0 NaN
2 3.0 6.0
In [97]: df.fillna(0)
Out[97]:
a b
0 0.0 2.0
1 1.0 0.0
2 3.0 6.0
In [98]: df.fillna(df.mean())
Out[98]:
a b
0 2.0 2.0
1 1.0 4.0
2 3.0 6.0
In [120]: df.dropna()
Out[120]:
a b
2 3.0 6.0
In [121]: df[df.isna()]=0
In [122]: df
Out[122]:
a b
0 0.0 2.0
1 1.0 0.0
2 3.0 6.0
fillna
方法用于直接填充缺失值,可傳入標量,對所有列填充同樣的值,也可傳入字典或系列,對不同列填充不同的值。
dropna
方法用于直接刪除帶卻缺失值的行或列:axis
參數指定刪除行(0)或列(1);how
參數指定刪除的條件,'all'
表示全部值為NaN時刪除,'any'
表示有一個為NaN時刪除;thresh
參數設置在出現幾個NaN時執行刪除。
isna
方法配合索引器也能對缺失值進行更新,可通過賦值標量對所有列填充同樣的值,或是賦值序列對不同列填充不同的值。
六. 排序與去重
1. 直接與間接排序
In[5]: df=pd.DataFrame([[2,'a'],[1,'c'],[3,'b']],columns=['col1','col2'],index=[3,2,1])
In[6]: df
Out[6]:
col1 col2
3 2 a
2 1 c
1 3 b
In[7]: df.sort_index()
Out[7]:
col1 col2
1 3 b
2 1 c
3 2 a
In[8]: df.sort_values('col1')
Out[8]:
col1 col2
2 1 c
3 2 a
1 3 b
In [21]: df.loc[df['col2'].sort_values().index]
Out[21]:
col1 col2
3 2 a
1 3 b
2 1 c
sort_index
方法可以按索引排序,axis
參數指定排序的軸,默認0,level
參數指定用于排序的多級索引的級別,默認None,ascending
參數指定是否升序,默認True。
sort_values
方法可以按指定鍵排序,by
參數指定用于排序的鍵,axis
參數指定排序的軸,默認0,ascending
參數指定是否升序,默認True。
間接排序可通過loc
方法傳入排序后的標簽索引實現,排序前兩個數據模型的索引必須一致;iloc
方法類似,需要傳入經過numpy的argsort
方法排序后的位置索引。
2. 去重
In[8]: df=pd.DataFrame({'a':[1,2,2,2],'b':[3,3,4,4]})
In[10]: df
Out[10]:
a b
0 1 3
1 2 3
2 2 4
3 2 4
In[11]: df.duplicated()
Out[11]:
0 False
1 False
2 False
3 True
dtype: bool
In[12]: df.drop_duplicates()
Out[12]:
a b
0 1 3
1 2 3
2 2 4
In[14]: df.drop_duplicates('a',keep='last')
Out[14]:
a b
0 1 3
3 2 4
duplicated
方法用于返回標識去重結果的一維布爾數組,保留的項為True。subset
參數指定參與去重的行或列標簽,默認使用所有列;keep
參數指定保留方式,'first'
表示保留第一項,'last'
表示保留最后一項,None
表示不保留。
drop_duplicates
方法用于返回去重結果。subset
和keep
參數的作用和duplicated
一樣。
七. 亂序和抽樣
1. 隨機排序
In [24]: df=pd.DataFrame({'a':[1,2,3],'b':[4,5,6]})
In [25]: df.iloc[np.random.permutation(df.shape[0])]
Out[25]:
a b
1 2 5
0 1 4
2 3 6
In [27]: df.sample(frac=1.)
Out[27]:
a b
0 1 4
2 3 6
1 2 5
隨機排序,用于打亂數據集。一種方法是通過numpy生成亂序索引,然后應用在pandas的iloc
索引方法上;另一種方法是使用pandas的抽樣方法sample
,設置抽樣比例frac
參數為1.,采用默認的不放回抽樣的方式,也可以達到同樣的效果。
2. 抽樣
In [34]: df.sample(n=2)
Out[34]:
a b
1 2 5
2 3 6
In [36]: df.sample(frac=0.8,replace=True)
Out[36]:
a b
1 2 5
1 2 5
sample
方法用于抽樣,第一個參數n
設置抽樣數量,第二個參數frac
設置抽樣比例,第三個參數replace
設置是否放回,默認False
,第四個參數weight
可設置樣本權重,第五個參數random_state
設置隨機數種子。
八. 讀寫
1. 讀寫csv
In [13]: df=pd.DataFrame({'a':[1,2],'b':[3,4]},index=['r1','r2'])
In [14]: df.to_csv()
Out[14]: ',a,b\nr1,1,3\nr2,2,4\n'
In [15]: df.to_csv(index=False)
Out[15]: 'a,b\n1,3\n2,4\n'
In [16]: df.to_csv("d:\\test.csv",index=False)
In [17]: df2=pd.read_csv("d:\\test.csv")
In [18]: df2
Out[18]:
a b
0 1 3
1 2 4
to_csv
方法用于寫入csv文件:
參數path_or_buf
設置文件路徑或對象,默認為None
,表示直接返回完整的內容字符串;
參數sep
設置分隔符,長度為1的字符串,默認為','
;
參數na_rep
設置缺失值填充,默認''
;
參數float_format
設置浮點數的格式字符串,如'%.2f'
表示保留兩位小數;
參數columns
設置要寫的列,默認None
,表示全部;
參數header
設置是否寫入列名,默認True
,如果給出字符串列表,則作為列別名;
參數index
設置是否寫入行索引標簽,默認True
;
參數index_label
設置行索引列的列名,默認None
,會直接使用索引的名稱,不寫入列名需要設置為False
;
參數encoding
設置編碼格式,python3默認utf-8
;
參數chunksize
設置每次批量寫入的塊大小,默認一次寫入全部數據。
read_csv
方法用于讀取csv文件:
參數filepath_or_buffer
設置文件路徑或類文件對象,必須賦值;
參數sep
設置分隔符,長度為1的字符串,默認為','
;
參數header
設置作為列名的行號,可傳入列表,會讀取為多級索引,默認是第一行作為列名,當通過names
顯示傳遞列名時,該設置無效,另外,該參數會跳過注釋行和空行;
參數names
設置列名列表,默認為None
,如果文件不含列名,header
也應設置為None
,該參數不能有重復項,會報錯;
參數index_col
設置作為行標簽的列號,可傳入列表,會讀取為多級索引,默認不設置;
參數usecols
設置要讀取的列列表,可以是列位置(int)或是列名(str)的列表,也可以傳入對列名進行邏輯判斷的函數,結果為True
的列將被返回;
參數prefix
設置默認列名前綴,在沒有設置列名時會將該前綴組合列號作為列名;
參數dtype
設置數據類型,dict
類型,鍵為列名,值為numpy數據類型,默認None
;
參數skiprows
設置開頭要跳過的行數,需要傳入int
,也可以設置要跳過的行號,傳入list of int
或對行號進行邏輯判斷的函數;
參數skipfooter
設置尾部要跳過的行數,需要傳入int
;
參數nrows
設置要讀取的行數,用于分批讀取大文件;
參數na_filter
設置是否檢測缺失值,默認True
,在確定沒有缺失值的情況下可以關閉以提升讀取性能;
參數skip_blank_lines
設置是否跳過空行,默認True
;
參數encoding
設置編碼格式,python3默認utf-8
;
參數error_bad_lines
設置列數異常的壞行是否報錯,默認True
,False
時會直接剔除壞行;
參數chunksize
設置分塊的大小,如果設置,會按該大小分塊讀取并以迭代器返回。
2. 讀寫excel
In [5]: df=pd.DataFrame({'a':[1,2],'b':[3,4]},index=['r1','r2'])
In [7]: df.to_excel('d:\\test.xlsx',sheet_name='test1',index=False)
In [8]: df2=pd.read_excel('d:\\test.xlsx',sheet_name=0)
In [9]: df2
Out[9]:
a b
0 1 3
1 2 4
to_excel
方法用于寫入xls或xlsx文件:
參數excel_writer
設置文件路徑或ExcelWriter,必須賦值;
參數sheet_name
設置要讀取的工作表名稱,默認'Sheet1'
;
參數na_rep
設置缺失值填充,默認''
;
參數float_format
設置浮點數的格式字符串,如'%.2f'
表示保留兩位小數;
參數columns
設置要寫入的列,為列名的序列;
參數header
設置是否寫入列名,默認True
,當輸入字符串列表時會當作列的別名;
參數index
設置是否寫入行索引標簽,默認True
;
參數index_label
設置行索引列的列名,當存在多級索引時應當輸入字符串列表,默認None
,會直接使用索引的名稱;
參數startrow
設置寫入的起始行,默認0
;
參數startcol
設置寫入的起始列,默認0
;
參數merge_cells
設置單元格是否合并,默認True
。
read_excel
方法用于讀取xls或xlsx文件:
參數io
設置文件路徑或Excel文件對象,必須賦值;
參數sheet_name
設置要讀取的工作表,可以傳入序號(int)或工作表名(str)或是包含前兩種的列表,傳入None
表示全部,默認0
;
參數header
設置解析為列名的行號,傳入行號的列表時會解析為多級索引,如果沒有列名,需要設置為None
;
參數names
設置列名,與header
配合使用,默認None
;
參數index_col
設置解析為行標簽的列號,傳入列號的列表時會解析為多級索引,默認None
;
參數usecols
設置需要返回的列,可傳入列號的列表list of int
、列名的列表list of str
、用逗號分隔的列名序列(例如 'A,B,C')或用冒號標識的列名范圍(例如 'A:E')str
,也可傳入對列名進行邏輯判斷的函數,結果為True
的列將被返回;
參數dtype
設置數據類型,dict
類型,鍵為列名,值為numpy數據類型,默認None
;
參數skiprows
設置開頭要跳過的行數,需要傳入int
,也可以設置要跳過的行號,傳入list of int
或對行號進行邏輯判斷的函數;
參數skipfooter
設置尾部要跳過的行數,需要傳入int
。
3. 讀寫sql
In [21]: import sqlalchemy as sqla
...: username='sa'
...: password='123456'
...: server='127.0.0.1'
...: database='Test'
...: charset='utf8'
...: engine = sqla.create_engine('mssql+pymssql://{}:{}@{}/{}?charset={}'.format(username,password,server,database,charset))
In [23]: df=pd.DataFrame({'a':[1,2],'b':[3,4]},index=['r1','r2'])
In [24]: df.to_sql('test1',engine,if_exists='append',index=False)
In [25]: df.to_sql('test1',engine,if_exists='append',index=False)
In [27]: df2=pd.read_sql('select * from test1',engine)
In [28]: df2
Out[28]:
a b
0 1.0 3.0
1 2.0 4.0
2 1.0 3.0
3 2.0 4.0
to_sql
方法用于寫入數據庫:
參數name
設置要寫入的表名,str
類型;
參數conn
設置數據庫連接,sqlalchemy.engine.Engine
類型,需要配合sqlalchemy庫使用,通過create_engine
方法創建,連接字符串格式形如'{數據庫類型}+{驅動名}://{用戶名}:{密碼}@{服務器地址}:{端口號}/{數據庫名}?charset={字符集}'
;
參數if_exists
設置表存在時的處理方式,'fail'
表示拋出異常,'replace'
表示替換現有表,'append'
表示作為新數據插入現有表,默認'fail'
;
參數index
設置行索引標簽是否作為一列寫入,默認True
;
參數index_label
設置行索引標簽列的列名,當存在多級索引時應當輸入字符串列表,默認None
,會直接使用索引的名稱;
參數chunksize
設置每次批量寫入的塊大小,默認一次寫入全部數據;
參數dtype
設置寫入的數據類型,dict
類型,鍵為列名,值為sqlalchemy數據類型;
read_sql
方法用于讀取數據庫:
參數sql
設置要執行的sql查詢或表名;
參數conn
設置數據庫連接,sqlalchemy.engine.Engine
類型;
參數index_col
設置作為行標簽索引的列名,傳入列名的列表時會生成多級索引;
參數coerce_float
設置是否嘗試將一些非字符串非數字對象(如decimal.Decimal)的值轉換為浮點數,默認True
;
參數params
設置傳遞給執行sql的參數列表,具體格式由使用的驅動決定;
參數parse_dates
設置要解析為時間的列名列表,默認None
;
參數columns
設置要讀取的列,僅在sql
參數傳入表名時有效,默認None
讀取全部列;
參數chunksize
設置分塊的大小,如果設置,會按該大小分塊讀取并以迭代器返回。
九. 快速繪圖
準備好pandas數據對象就可以調用方法直接繪圖,pandas提供的快速繪圖只適用于單次繪圖,不便于構建復雜的圖表,如有需要,使用matplotlib的方法創建圖像和子圖。
1. 曲線圖
In [30]: df=pd.DataFrame({'a':[1,1.5,2.5,4],'b':[3,2.1,3.2,1],'c':[1,2,3,4]})
In [53]: fig=plt.figure(figsize=(12,4))
...:
...: ax1=fig.add_subplot(1,2,1)
...: df.plot.line(ax=ax1)
...:
...: ax2=fig.add_subplot(1,2,2)
...: df.plot.line(x='c',y=['a','b'],ax=ax2)
...:
...: #plt.show()
Out[53]: <matplotlib.axes._subplots.AxesSubplot at 0x2aefe00ddd8>
參數x
設置作為x軸數據的列名(只能一個),參數y
設置作為y軸數據的列名/列名列表,參數ax
設置子圖對象,默認None
單獨繪制。
plt.figure
用于創建圖像,figsize
用于設置圖像大小,tuple類型,格式為(weight,height)
;
Figure.add_subplot
用于創建子圖,第一個參數設置縱向分區個數,第二個參數設置橫向分區個數,第三個參數設置是第幾個子圖,是按分區先橫后縱排列的;
plt.plot
用于顯示繪制好的圖像,在當前場景下可以省略,ipython調用完pandas的繪圖方法后會直接顯示。
繪制曲線圖也可以使用plot(kind='line')
,參數kind
也可以省略,因為默認值就是'line'
。
2. 條形圖
In [30]: df=pd.DataFrame({'a':[1,1.5,2.5,4],'b':[3,2.1,3.2,1],'c':[1,2,3,4]})
In [147]: fig=plt.figure(figsize=(12,4))
...:
...: ax1=fig.add_subplot(1,2,1)
...: df.plot.bar(ax=ax1)
...:
...: ax2=fig.add_subplot(1,2,2)
...: df.plot.bar(stacked=True,ax=ax2)
Out[147]: <matplotlib.axes._subplots.AxesSubplot at 0x2aeff4f17b8>
參數stacked
設置條形圖是否堆疊。
水平條形圖需要改用DataFrame.plot.barh
方法。
3. 直方圖
In [205]: df=pd.DataFrame({'a':[1,2,2,3],'b':[3,3,3,4],'c':[1,2,3,4]})
In [210]: fig=plt.figure(figsize=(12,4))
...:
...: ax1=fig.add_subplot(1,2,1)
...: df.plot.hist(alpha=0.5,ax=ax1)
...:
...: ax2=fig.add_subplot(1,2,2)
...: df.plot.hist(stacked=True,bins=4,ax=ax2)
Out[210]: <matplotlib.axes._subplots.AxesSubplot at 0x2aefff32080>
參數alpha
設置透明度,參數stacked
設置是否堆疊,參數bins
設置分箱數。
配合diff
可以繪制按列拆分為子圖的直方圖:
In [165]: df.diff().hist(bins=4)
Out[165]:
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x000002AE805A4748>,
<matplotlib.axes._subplots.AxesSubplot object at 0x000002AE805E3D68>],
[<matplotlib.axes._subplots.AxesSubplot object at 0x000002AE80615390>,
<matplotlib.axes._subplots.AxesSubplot object at 0x000002AE8063DA20>]],
dtype=object)
4. 箱線圖
In [166]: df = pd.DataFrame(np.random.rand(10, 4),columns=['A','B','C','D'])
In [167]: df.plot.box()
Out[167]: <matplotlib.axes._subplots.AxesSubplot at 0x2aeff644080>
5. 散點圖
In[185]: df=pd.DataFrame(np.random.rand(50,3),columns=['a','b','c'])
In[186]: fig=plt.figure(figsize=(12,4))
...:
...: ax1=fig.add_subplot(1,2,1)
...: df.plot.scatter(x='a',y='b',s=df['c']*200,ax=ax1)
...:
...: ax2=fig.add_subplot(1,2,2)
...: df[df['c']>=0.5].plot.scatter(x='a',y='b',color='b',label='c1',ax=ax2)
...: df[df['c']<0.5].plot.scatter(x='a',y='b',color='g',label='c2',ax=ax2)
Out[186]: <matplotlib.axes._subplots.AxesSubplot at 0x2ae81a82e48>
參數
x
設置作為x軸數據的列名(只能一個),參數y
設置作為y軸數據的列名(只能一個),參數s
設置點的大小,參數color
設置點的顏色,參數label
設置標簽,需要為每個類別繪制不同顏色的點時,篩選出每個類別的數據分別繪制到同一個子圖上,并指定顏色和標簽。
6. 餅圖
In [203]: df=pd.DataFrame(2*np.random.rand(3,2),index=['a','b','c'],columns=['p1','p2'])
In [204]: df.plot.pie(y='p1',figsize=(4,4))
Out[204]: <matplotlib.axes._subplots.AxesSubplot at 0x2ae81f66cf8>
In [206]: df.plot.pie(subplots=True,figsize=(8.5,4))
Out[206]:
array([<matplotlib.axes._subplots.AxesSubplot object at 0x000002AE8171BEB8>,
<matplotlib.axes._subplots.AxesSubplot object at 0x000002AEFFFD78D0>],
dtype=object)
有兩種繪制方式,一是參數y
指定一個列作為取值繪制餅圖,二是設置參數subplots
為True
,會用每個列的數據繪制子圖。
figsize
是繪圖的通用參數,用于設置圖像大小。