[python][科學計算][pandas]使用指南

最後一次更新日期: 2019/9/23python

新增字符串和時間處理的簡要介紹
缺失值填充、刪除、讀寫excel小節作了少量補充
第四章節補充了使用行列迭代器的方法
第五章節補充了設置索引、重置索引、重命名索引的方法
第三章節補充了基本運算符及對應函數的參考列表、移位與差量計算正則表達式

pandas是基於numpy的數據分析庫,提供一些更易用的數據模型和大量高效的統計方法。sql

使用前先導入模塊:數據庫

import pandas as pdapi

按需導入如下模塊:數組

import numpy as npbash

import matplotlib.pyplot as plt服務器

點擊下方連接可前往各小節app

使用指南1 - 數據模型與屬性 (索引,數據序列,數據框,分類數據)dom

使用指南2 - 數據類型與轉換 (數據類型,類型轉換)

使用指南3 - 數組與統計運算 (基本運算和標量值函數,統計方法,自定義函數,廣播)

使用指南4 - 查詢與關聯 (索引查找,行列迭代,錶鏈接)

使用指南5 - 增刪改 (更新,增長,刪除,變動索引,行列轉置,缺失值填充)

使用指南6 - 排序與去重 (直接與間接排序,去重)

使用指南7 - 亂序與抽樣 (隨機排序,抽樣)

使用指南8 - 讀寫 (讀寫csv,讀寫excel,讀寫sql)

使用指南9 - 快速繪圖 (曲線圖,條形圖,直方圖,箱線圖,散點圖,餅圖)

使用指南10 - 特殊類型處理 (字符串,時間)

一. 數據模型與屬性

返回目錄

1. 索引Index

numpy中只有位置索引,而pandas還增長了標籤索引,依賴於一個專用的Index類型。

常規索引

pd.Index([1,2,3])
Out[64]: Int64Index([1, 2, 3], dtype='int64')

pd.Index([1.,2.,3.])
Out[65]: Float64Index([1.0, 2.0, 3.0], dtype='float64')

pd.Index(['a','b','c'])
Out[66]: Index(['a', 'b', 'c'], dtype='object')

pd.Index(range(10))
Out[67]: RangeIndex(start=0, stop=10, step=1)

pd.Index(range(10)).values
Out[68]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int64)

import datetime as dt
dt1=dt.datetime.now()
dt2=dt1+dt.timedelta(days=1)

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計算也會自動產生多級索引。

midx=pd.MultiIndex(levels=[['a','b'],['c','d']],labels=[[1,1,0,0],[0,1,0,1]],name=['idx1','idx2'])

midx
Out[6]: 
MultiIndex(levels=[['a', 'b'], ['c', 'd']],
           labels=[[1, 1, 0, 0], [0, 1, 0, 1]],
           names=['idx1', 'idx2'])

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'])

midx.swaplevel(0,1)
Out[11]: 
MultiIndex(levels=[['c', 'd'], ['a', 'b']],
           labels=[[0, 1, 0, 1], [1, 1, 0, 0]],
           names=['idx2', 'idx1'])

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_levelsset_labelsset_names能夠設置總體或是某一級別的索引屬性,經過level參數指定級別,默認設置總體; swaplevel能夠交換級別,droplevel能夠刪除級別,sortlevel能夠對指定級別排序; from_arrayfrom_tuplesfrom_productfrom_frame方法可從其餘結構的數據中建立索引。

2. 數據序列Series

s=pd.Series([1,2,3,4],name='s1')

s
Out[100]: 
0    1
1    2
2    3
3    4
Name: s1, dtype: int64

pd.Series([[1,2],[3,4]],index=['row1','row2'])
Out[101]: 
row1    [1, 2]
row2    [3, 4]
dtype: object

s.dtype
Out[102]: dtype('int64')

s.name
Out[103]: 's1'

s.values
Out[104]: array([1, 2, 3, 4], dtype=int64)

s.index
Out[105]: RangeIndex(start=0, stop=4, step=1)

s.shape
Out[106]: (4,)
複製代碼

核心數據模型其一,由序列名name、標籤索引index、值數組(一維)values組成。用於存放一維數據,只有一個軸方向:0,shape屬性能夠查看數據集的形狀。

建立時只能接收一維序列數據(list,tuple,ndarray),超過一維的將後面的維度看做元素的維度,會根據傳入的數據自動判斷類型,也可經過dtype參數顯示指定。

默認狀況下會生成範圍索引,可經過index參數指定一個一維序列做爲索引,也可在建立後直接爲index屬性賦值。

3. 數據框DataFrame

df=pd.DataFrame([[1,'a'],[2,'b']],columns=['col1','col2'])

df
Out[108]: 
   col1 col2
0     1    a
1     2    b

df.dtypes
Out[113]: 
col1     int64
col2    object
dtype: object

df.index
Out[114]: Int64Index([1, 2], dtype='int64', name='col1')

df.columns
Out[116]: Index(['col1', 'col2'], dtype='object')

df.values
Out[117]: 
array([[1, 'a'],
       [2, 'b']], dtype=object)

df.col2
Out[125]: 
col1
1    a
2    b
Name: col2, dtype: object

pd.DataFrame({'col1':[1,3],'col2':['a','b']})
Out[126]: 
   col1 col2
0     1    a
1     3    b

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提供了分類數據類型用於約束此類數據,該類型會限制分類標籤的取值,並可爲分類標籤提供排序依據。

pd.Categorical(['a','b','b','c'],categories=['a','b'],ordered=True)
Out[14]: 
[a, b, b, NaN]
Categories (2, object): [a < b]

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. 類型轉換

df=pd.DataFrame([[1,'2'],[3,'a']],columns=['col1','col2'])

df.dtypes
Out[49]: 
col1     int64
col2    object
dtype: object

df.col1.astype('float')
Out[50]: 
0    1.0
1    3.0
Name: col1, dtype: float64

pd.to_numeric(df.col2,errors='ignore')
Out[52]: 
0    2
1    a
Name: col2, dtype: object

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的標量值函數也可直接使用,這些運算都是將本來做用於單個元素的運算拓展到整個數組。

df=pd.DataFrame([[1,'2'],[3,'a']],columns=['col1','col2'])

df+df
Out[57]: 
   col1 col2
0     2   22
1     6   aa

np.sqrt(df.col1)
Out[201]: 
0    1.000000
1    1.732051
Name: col1, dtype: float64
複製代碼

使用的運算符和函數必須對參與運算的全部數據類型都是有意義的,不然會報錯。

匹配方式

s1=pd.Series([1,2,3,4],index=[0,1,2,3])
s2=pd.Series([5,6,7,8],index=[1,2,3,4])

s1+s2
Out[156]: 
0     NaN
1     7.0
2     9.0
3    11.0
4     NaN
dtype: float64
複製代碼

此處須要注意pandas和numpy的區別,pandas的數組運算在元素匹配上是基於標籤索引的,未能匹配到的位置會被替換爲NaN,numpy則是基於位置索引。

基本運算符與對應的函數

運算符 對應函數 說明
+ add 相加
- sub 相減
* mul 相乘
/ div 相除
// floordiv 整除
% mod 取餘
** pow 指數冪
== eq 相等
!= ne 不等
>= ge 大於等於
<= le 小於等於
> gt 大於
< lt 小於
~ - 按位取反
& - 按位與
| - 按位或
^ - 按位異或

pandas數據模型的邏輯運算不能使用not、and、or,應當使用~、&、|;
位移運算符<<、>>也不可用於pandas數據模型。

2. 統計方法

聚合函數

pandas繼承了numpy的聚合函數:summeanmaxmin等。 可經過SeriesDataFrame的方法調用,或是調用numpy下的靜態方法。

df.sum()
Out[58]: 
col1     4
col2    2a
dtype: object

np.max(df)
Out[60]: 
col1    3
col2    a
dtype: object

df.agg({'col1':'max','col2':'sum'})
Out[114]: 
col1     3
col2    2a
dtype: object

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方法用於分組統計。

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

result=df.groupby(by=['col1','col2']).agg(['max','min'])

result
Out[94]: 
          col3    
           max min
col1 col2         
a    c       1   1
     d       2   2
b    d       3   3

result.sum(level=0)
Out[95]: 
     col3    
      max min
col1         
a       3   3
b       3   3

gb=df.groupby(by=['col1','col2'])

gb.groups
Out[141]: 
{('a', 'c'): Int64Index([0], dtype='int64'),
 ('a', 'd'): Int64Index([1], dtype='int64'),
 ('b', 'd'): Int64Index([2], dtype='int64')}

gb.get_group(('a','c'))
Out[142]: 
  col1 col2  col3
0    a    c     1
複製代碼

只調用groupby方法會獲得一個DataFrameGroupBy對象,經過其groups方法可查看全部分組信息,get_group方法可獲取指定分組。 該對象可調用各類聚合函數,或調用agg方法進行復合的聚合統計,返回包含多級索引的DataFrame統計結果表,對於結果表,能夠繼續應用統計函數並經過level參數指定索引級別進行二次統計。

移位與差別計算

在分析數據時會有須要計算相鄰記錄之間變化量的狀況,可經過shift方法實現記錄的移位再相減或直接使用diff方法。

s=pd.Series([1,2,3,4])

s
Out[28]: 
0    1
1    2
2    3
3    4
dtype: int64

s.shift()
Out[29]: 
0    NaN
1    1.0
2    2.0
3    3.0
dtype: float64

s.shift(periods=2)
Out[32]: 
0    NaN
1    NaN
2    1.0
3    2.0
dtype: float64

s-s.shift()
Out[30]: 
0    NaN
1    1.0
2    1.0
3    1.0
dtype: float64

s.diff()
Out[33]: 
0    NaN
1    1.0
2    1.0
3    1.0
dtype: float64

s.pct_change()
Out[34]: 
0         NaN
1    1.000000
2    0.500000
3    0.333333
dtype: float64
複製代碼

shift方法用於指定方向上的數據移位,diff方法用於指定位移下的變化量計算,pct_change方法用於指定位移下的變化率計算。periods參數指定位移量,默認1,axis指定軸方向,默認0。

3. 應用自定義函數

除pandas和numpy提供的函數外,還能夠自定義函數並使用applyapplymapmap方法快速應用於整個數據集。

df.apply(lambda x: x.col1+x.col2, axis=1)
Out[119]: 
0    3
1    7
dtype: int64

def add(row):
    return row.col1+row.col2

df.apply(add, axis=1)
Out[121]: 
0    3
1    7
dtype: int64

df.applymap(lambda x: x*2)
Out[122]: 
   col1  col2
0     2     4
1     6     8

def double(item):
    return item*2

df.applymap(double)
Out[124]: 
   col1  col2
0     2     4
1     6     8

s=pd.Series(['a','b','b'])

s.map(lambda x: x*2)
Out[129]: 
0    aa
1    bb
2    bb
dtype: object

s.map({'a':'c','b':'d'})
Out[130]: 
0    c
1    d
2    d
dtype: object
複製代碼

DataFrameapplyapplymap兩個方法: apply將函數應用於每行或者每列,axis參數指定應用函數的軸方向,值爲0表示按列應用,即逐列做爲函數的參數進行計算,值爲1表示按行應用,默認爲0; applymap將函數應用於每一個元素。

Series只有一個map方法,用於將函數應用於元素,除此之外,還提供值映射的功能,輸入dict類型時會根據key-value映射將相應的值替換。

支持lambda匿名函數。

4. 廣播

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]])

df22+l2
Out[99]: 
   0  1
0  2  4
1  4  6

df22+a2
Out[100]: 
   0  1
0  2  4
1  4  6

df22+s2
Out[101]: 
   0  1
0  2  4
1  4  6

df22+df21
Out[102]: 
   0   1
0  2 NaN
1  5 NaN

df22+df12
Out[103]: 
     0    1
0  2.0  4.0
1  NaN  NaN

df23+s2
Out[104]: 
     0    1   2
0  4.0  6.0 NaN
1  7.0  9.0 NaN

df21+df12
Out[130]: 
     0   1
0  2.0 NaN
1  NaN NaN
複製代碼

pandas的廣播機制繼承自numpy但有不同的地方:
標量值會與DataFrameSeries中每一個元素進行一樣的計算;
Series或一維list或一維ndarray會與DataFrame的每一行進行運算,Series在長度不足以匹配DataFrame的行時不足部分會替換爲NaN,其餘兩種長度不足會報錯;
DataFrameDataFrame進行運算會按元素匹配,不管行列,長度不足的部分都會替換爲NaN
二維ndarrayDataFrame的運算遵循numpy的廣播規則,長度不足且爲1的軸會被廣播至同等大小; 二維listDataFrame的運算不被支持。

四. 查詢和關聯

返回目錄

1. 索引查找

(1). 索引器格式

單值選取:[value,...]
多值選取:[[value1,value2],...]
範圍選取:[start:end:step,...]

start表示區間的開始,默認值0,end表示區間的結束(不包含),默認值等於軸長度,step表示選取的步長,默認值1,採用默認值的參數能夠省略,[:,...]表示對應軸方向上所有選取。

pandas中索引器的格式與numpy差很少,但用法有區別。pandas除了numpy的位置索引,還增長了標籤索引,雖然能夠對SeriesDataFrame直接使用索引器,但用法被嚴格限制,建議改用ilocloc方法進行索引。

(2). 直接索引

df=pd.DataFrame(np.arange(1,10).reshape((3,3)),columns=['col1','col2','col3'],index=['row1','row2','row3'])

df[0:3:2]
Out[158]: 
      col1  col2  col3
row1     1     2     3
row3     7     8     9

df['row1':'row3':2]
Out[161]: 
      col1  col2  col3
row1     1     2     3
row3     7     8     9

df['col2']
Out[162]: 
row1    2
row2    5
row3    8
Name: col2, dtype: int32

df[['col1','col3']]
Out[163]: 
      col1  col3
row1     1     3
row2     4     6
row3     7     9

df['col2'][1:3]
Out[168]: 
row2    5
row3    8
Name: col2, dtype: int32
複製代碼

直接索引提供了有限的幾種使用方式:按行位置進行索引切片、按行標籤進行索引切片、按列標籤取列、按列標籤列表取多列、布爾索引篩選行、索爾索引篩選元素等。 一次索引器只能使用一種方式,不能行列同時操做,若有須要,可進行連續索引。

(3). loc和iloc索引

df.loc['row1','col1']
Out[169]: 1

df.loc['row1':'row3':2,'col1':'col3':2]
Out[170]: 
      col1  col3
row1     1     3
row3     7     9

df.iloc[0,0]
Out[185]: 1

df.iloc[0:3:2,0:3:2]
Out[186]: 
      col1  col3
row1     1     3
row3     7     9
複製代碼

loc專用於標籤索引,iloc專用於位置索引,索引器可接收單值、列表、範圍、布爾索引,可同時索引行和列。

(4). 布爾索引

df>5
Out[190]: 
       col1   col2   col3
row1  False  False  False
row2  False  False   True
row3   True   True   True

df[df>5]
Out[191]: 
      col1  col2  col3
row1   NaN   NaN   NaN
row2   NaN   NaN   6.0
row3   7.0   8.0   9.0

df['col1']>2
Out[192]: 
row1    False
row2     True
row3     True
Name: col1, dtype: bool

df.loc[df['col1']>2]
Out[193]: 
      col1  col2  col3
row2     4     5     6
row3     7     8     9

df.loc[df['col1']>2,df.iloc[1]>5]
Out[196]: 
      col3
row2     6
row3     9

df.iloc[df['col1'].values>2]
Out[208]: 
      col1  col2  col3
row2     4     5     6
row3     7     8     9
複製代碼

布爾索引是一種比較特殊的索引,經過對pandas或numpy的數據模型進行比較運算能夠獲得,本質上就是數據類型爲boolSerieDataFramendarray,與源數據形狀相同,用於標識每一個元素是否符合篩選條件。在索引器中使用布爾索引能夠篩選出符合條件的數據。

在直接索引時,二維布爾索引能夠用於篩選DataFrame的元素,形狀不變,不符合條件的元素會被替換爲NaN,這一點和numpy不同,numpy進行一樣形式的篩選時會將符合條件的元素構造爲新的一維數組返回;一維布爾索引只能夠用於篩選行數據;

在使用loc索引時,不能使用二維布爾索引,只能針對每一個軸使用一維布爾索引,而且必須是由Series運算獲得的帶有標籤索引的布爾索引; 在使用iloc索引時,一樣不能使用二維布爾索引,只能針對每一個軸使用一維布爾索引,而且必須是由一維ndarray運算獲得的不含標籤索引的布爾索引(Series.values可獲得對應的ndarray)。

(5). 指定值查找

df=pd.DataFrame({'a':[np.nan,1,2],'b':[3,np.nan,4]})

df
Out[142]: 
     a    b
0  NaN  3.0
1  1.0  NaN
2  2.0  4.0

df.isin([2,3])
Out[143]: 
       a      b
0  False   True
1  False  False
2   True  False

df.isna()
Out[144]: 
       a      b
0   True  False
1  False   True
2  False  False
複製代碼

isin方法用於查找存在於指定列表中的值,isna方法用於查找NaN值,兩方法都會返回布爾索引,一般結合索引器使用。

2. 行列迭代

pandas提供了迭代器用於遍歷行或者列。

(1). 行迭代

df=pd.DataFrame([{'a':1,'b':2,'c':3},{'a':4,'b':5,'c':6}])

for i,row in df.iterrows():
    print("\nrow(%s):\n%s"%(i,row))
    
row(0):
a    1
b    2
c    3
Name: 0, dtype: int64

row(1):
a    4
b    5
c    6
Name: 1, dtype: int64
複製代碼

(2). 列迭代

for j,col in df.iteritems():
    print("\ncol(%s):\n%s"%(j,col))
    
col(a):
0    1
1    4
Name: a, dtype: int64

col(b):
0    2
1    5
Name: b, dtype: int64

col(c):
0    3
1    6
Name: c, dtype: int64
複製代碼

3. 錶鏈接

pandas提供了相似於sql的joinmergeconcat方法進行錶鏈接。

(1). 索引鏈接

df1=pd.DataFrame([[1,2],[3,4]],columns=['col1','col2'],index=[1,0])
df2=pd.DataFrame([[5,6],[7,8]],columns=['col3','col4'],index=[0,1])

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). 鍵鏈接

df1=pd.DataFrame({'col1':[1,2,3],'col2':[4,5,6]})
df2=pd.DataFrame({'col2':[4,5,7],'col3':[1,2,2]})

df1.merge(df2)
Out[235]: 
   col1  col2  col3
0     1     4     1
1     2     5     2

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_onright_on參數(不一樣鍵)指定,默認會將兩表中都存在的鍵做爲鏈接鍵;how參數指定鏈接方式,有inner內鏈接、outer外鏈接、left左鏈接、right右鏈接 這幾種,默認爲inner

該方法纔是sql中join的等效方法。

(3). 拼接

df1=pd.DataFrame({'col1':[1,2,3],'col2':[4,5,6]})
df2=pd.DataFrame({'col2':[4,5,7],'col3':[1,2,2]})

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

pd.concat([df1,df2],join='inner')
Out[242]: 
   col2
0     4
1     5
2     6
0     4
1     5
2     7

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. 更新

df=pd.DataFrame({'a':[1,2],'b':[3,4]})

df.iloc[0,0]=0

df[df>2]+=1

df
Out[262]: 
   a  b
0  0  4
1  2  5

df['a']=[2,1]

df
Out[266]: 
   a  b
0  2  4
1  1  5

df[:]=[1,2]

df
Out[269]: 
   a  b
0  1  2
1  1  2
複製代碼

更新數據的方式與numpy同樣,索引篩選數據後直接賦值就好了,能夠對全部元素賦值同一個標量,也可賦值一樣形狀的數據集,或是對DataFrame每行賦值一樣的數據序列。

2. 增長

df=pd.DataFrame({'a':[1,2],'b':[3,4]})

df['c']=[5,6]

df
Out[248]: 
   a  b  c
0  1  3  5
1  2  4  6

df.loc[2]=-1

df
Out[253]: 
   a  b  c
0  1  3  5
1  2  4  6
2 -1 -1 -1

df.insert(0,'new',[0,0,0])

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. 刪除

df=pd.DataFrame({'a':[1,2,3],'b':[4,5,6]})

df[df['a']>2]
Out[277]: 
   a  b
2  3  6

df.drop([0,2])
Out[281]: 
   a  b
1  2  5

df.drop('a',axis=1)
Out[282]: 
   b
0  4
1  5
2  6
複製代碼

刪除數據最靈活的方法就是經過索引篩去不須要的數據。

也可經過drop刪除指定索引標籤的數據,labels指定要刪除的標籤,能夠是標量或是列表,axis參數指定查找索引標籤的軸,默認爲0。該方法是根據索引標籤而不是位置去刪除的,因此若是指定標籤存在重複,這些數據會一塊兒被刪除。

若想留存被刪除的列(好比想將該列插入另外一個位置),可以使用pop方法彈出列。

4. 變動索引

(1).設置索引

df=pd.DataFrame({'a':[1,2],'b':[3,4]})

df.set_index('a')
Out[46]: 
   b
a   
1  3
2  4

df.set_index(keys=['a','b'],drop=False)
Out[47]: 
     a  b
a b      
1 3  1  3
2 4  2  4
複製代碼

set_index方法能夠將指定列設置爲索引:
第一個參數keys指定列名;
第二個參數drop設置是否要刪除被設置爲索引的列,默認True
第三個參數append設置是否追加到現有索引上,默認False
第四個參數replace設置是否在當前對象上修改,默認False

(2).重置索引

在有些狀況下,好比進行過一系列的表關聯和分組計算後,DataFrame的索引會變得雜亂,這時候須要一個方法來快速重置索引。

df=pd.DataFrame([['a','c',1],['a','d',2],['b','d',3],['b','d',4]],
                columns=['col1','col2','col3'])

r=df.groupby(['col1','col2']).sum()

r
Out[34]: 
           col3
col1 col2      
a    c        1
     d        2
b    d        7

r.reset_index(drop=True)
Out[37]: 
   col3
0     1
1     2
2     7

r.reset_index(level=1)
Out[38]: 
     col2  col3
col1           
a       c     1
a       d     2
b       d     7
複製代碼

reset_index方法能夠將行索引重置,並將捨棄的索引信息做爲列插入DataFrame
第一個參數level能夠指定多級索引須要捨棄的級別,默認所有捨棄,索引會被還原爲RangeIndex
第二個參數drop能夠設置是否丟棄被重置的索引信息,該項設置爲True後索引信息不會被插入DataFrame,默認False
第三個參數replace設置是否在當前對象上修改,默認False

(3).重構索引

df=pd.DataFrame({'a':[1,2],'b':[3,4]})

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能夠指定新增行列的填充值。

(4).重命名索引

df=pd.DataFrame([{'a':1,'b':2,'c':3},{'a':4,'b':5,'c':6}])

df
Out[52]: 
   a  b  c
0  1  2  3
1  4  5  6

df.rename({'a':'e','b':'f','c':'g'},axis=1)
Out[50]: 
   e  f  g
0  1  2  3
1  4  5  6
複製代碼

rename方法能夠對現有索引標籤重命名:
第一個參數mapper用來指定映射關係,能夠是dict或是function,輸入原名稱,輸出新名稱;
第四個參數axis指定重命名的軸,行索引對應0,列索引對應1,默認0;
第六個參數replace設置是否在當前對象上修改,默認False

5. 行列轉置

df=pd.DataFrame({'a':[1,2],'b':[3,4]})

df
Out[134]: 
   a  b
0  1  3
1  2  4

df.T
Out[135]: 
   0  1
a  1  2
b  3  4
複製代碼

DataFrame.T用於實現行列轉置,整個數據集將沿左上至右下的對角線翻轉。 Series調用轉置方法是無效的,若是須要轉置,先調用to_frame方法轉爲DataFrame

6. 缺失值填充

df=pd.DataFrame({'a':[np.nan,1,3],'b':[2,np.nan,6]})

df
Out[96]: 
     a    b
0  NaN  2.0
1  1.0  NaN
2  3.0  6.0

df.fillna(0)
Out[97]: 
     a    b
0  0.0  2.0
1  1.0  0.0
2  3.0  6.0

df.fillna(df.mean())
Out[98]: 
     a    b
0  2.0  2.0
1  1.0  4.0
2  3.0  6.0

df.dropna()
Out[120]: 
     a    b
2  3.0  6.0

df[df.isna()]=0

df
Out[122]: 
     a    b
0  0.0  2.0
1  1.0  0.0
2  3.0  6.0
複製代碼

fillna方法用於填充缺失值,第一個參數value設置用於填充的值,可傳入標量,對全部列填充一樣的值,也可傳入字典或系列,對不一樣列填充不一樣的值;另外一種用法是給第二個參數method賦值,'ffill''bfill'分別表示用前一個和後一個有效值填充。

dropna方法用於直接刪除帶卻缺失值的行或列:axis參數指定刪除行(0)或列(1);how參數指定刪除的條件,'all'表示所有值爲NaN時刪除,'any'表示有一個爲NaN時刪除;thresh參數設置在出現幾個NaN時執行刪除。

isna方法配合索引器也能對缺失值進行更新,可經過賦值標量對全部列填充一樣的值,或是賦值序列對不一樣列填充不一樣的值。

六. 排序與去重

返回目錄

1. 直接與間接排序

df=pd.DataFrame([[2,'a'],[1,'c'],[3,'b']],columns=['col1','col2'],index=[3,2,1])

df
Out[6]: 
   col1 col2
3     2    a
2     1    c
1     3    b

df.sort_index()
Out[7]: 
   col1 col2
1     3    b
2     1    c
3     2    a

df.sort_values('col1')
Out[8]: 
   col1 col2
2     1    c
3     2    a
1     3    b

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. 去重

df=pd.DataFrame({'a':[1,2,2,2],'b':[3,3,4,4]})

df
Out[10]: 
   a  b
0  1  3
1  2  3
2  2  4
3  2  4

df.duplicated()
Out[11]: 
0    False
1    False
2    False
3     True
dtype: bool

df.drop_duplicates()
Out[12]: 
   a  b
0  1  3
1  2  3
2  2  4

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方法用於返回去重結果。subsetkeep參數的做用和duplicated同樣。

七. 亂序和抽樣

返回目錄

1. 隨機排序

df=pd.DataFrame({'a':[1,2,3],'b':[4,5,6]})

df.iloc[np.random.permutation(df.shape[0])]
Out[25]: 
   a  b
1  2  5
0  1  4
2  3  6

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. 抽樣

df.sample(n=2)
Out[34]: 
   a  b
1  2  5
2  3  6

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

df=pd.DataFrame({'a':[1,2],'b':[3,4]},index=['r1','r2'])

df.to_csv()
Out[14]: ',a,b\nr1,1,3\nr2,2,4\n'

df.to_csv(index=False)
Out[15]: 'a,b\n1,3\n2,4\n'

df.to_csv("d:\\test.csv",index=False)

df2=pd.read_csv("d:\\test.csv")

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設置列數異常的壞行是否報錯,默認TrueFalse時會直接剔除壞行;
參數chunksize設置分塊的大小,若是設置,會按該大小分塊讀取並以迭代器返回。

2. 讀寫excel

df=pd.DataFrame({'a':[1,2],'b':[3,4]},index=['r1','r2'])

df.to_excel('d:\\test.xlsx',sheet_name='test1',index=False)

df2=pd.read_excel('d:\\test.xlsx',sheet_name=0)

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

當sheetname不明確,須要獲取所有sheetname時,可用如下方法

excel=pd.ExcelFile(file_path)
excel.sheetname
複製代碼

3. 讀寫sql

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))

df=pd.DataFrame({'a':[1,2],'b':[3,4]},index=['r1','r2'])

df.to_sql('test1',engine,if_exists='append',index=False)
df.to_sql('test1',engine,if_exists='append',index=False)

df2=pd.read_sql('select * from test1',engine)

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. 曲線圖

df=pd.DataFrame({'a':[1,1.5,2.5,4],'b':[3,2.1,3.2,1],'c':[1,2,3,4]})

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. 條形圖

df=pd.DataFrame({'a':[1,1.5,2.5,4],'b':[3,2.1,3.2,1],'c':[1,2,3,4]})

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. 直方圖

df=pd.DataFrame({'a':[1,2,2,3],'b':[3,3,3,4],'c':[1,2,3,4]})

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能夠繪製按列拆分爲子圖的直方圖:

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. 箱線圖

df = pd.DataFrame(np.random.rand(10, 4),columns=['A','B','C','D'])

df.plot.box()
Out[167]: <matplotlib.axes._subplots.AxesSubplot at 0x2aeff644080>
複製代碼

5. 散點圖

df=pd.DataFrame(np.random.rand(50,3),columns=['a','b','c'])

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. 餅圖

df=pd.DataFrame(2*np.random.rand(3,2),index=['a','b','c'],columns=['p1','p2'])

df.plot.pie(y='p1',figsize=(4,4))
Out[204]: <matplotlib.axes._subplots.AxesSubplot at 0x2ae81f66cf8>
複製代碼

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指定一個列做爲取值繪製餅圖,二是設置參數subplotsTrue,會用每一個列的數據繪製子圖。 figsize是繪圖的通用參數,用於設置圖像大小。

十. 特殊類型處理

返回目錄

1. 字符串處理

(1). 運算符

df=pd.DataFrame([['a','head',1],['b','Body',2],['c','FOOT',3]],
                columns=['col1','col2','col3'])

df['col1']+df['col2']
Out[54]: 
0    ahead
1    bBody
2    cFOOT
dtype: object

df['col1']*df['col3']
Out[55]: 
0      a
1     bb
2    ccc
dtype: object
複製代碼

字符串類型支持兩種運算符操做:拼接(str + str)和重複(str * int)

(2). 字符串方法

Series.str下封裝了用於字符串處理的方法,python中str類的大部分方法都被繼承了。 下面演示一些經常使用的方法:

索引器

df['col2'].str[:2]
Out[60]: 
0    he
1    Bo
2    FO
Name: col2, dtype: object
複製代碼

字符串長度

df['col2'].str.len()
Out[73]: 
0    4
1    4
2    4
Name: col2, dtype: int64
複製代碼

大小寫轉換

#轉大寫
#isupper方法判斷是否大寫
df['col2'].str.upper()
Out[56]: 
0    HEAD
1    BODY
2    FOOT
Name: col2, dtype: object

#轉小寫
#islower方法判斷是否大寫
df['col2'].str.lower()
Out[57]: 
0    head
1    body
2    foot
Name: col2, dtype: object

#首字母大寫
df['col2'].str.capitalize()
Out[58]: 
0    Head
1    Body
2    Foot
Name: col2, dtype: object

#大小寫互轉
df['col2'].str.swapcase()
Out[59]: 
0    HEAD
1    bODY
2    foot
Name: col2, dtype: object
複製代碼

填充

#填充至width長度
#side可設置'left'/'right'/'both'
df['col2'].str.pad(width=10, side='right', fillchar='-')
Out[63]: 
0    head------
1    Body------
2    FOOT------
Name: col2, dtype: object

#居中填充
#等效於pad(side='both')
df['col2'].str.center(width=11, fillchar='*')
Out[66]: 
0    ****head***
1    ****Body***
2    ****FOOT***
Name: col2, dtype: object
複製代碼

拼接

#將一列字符串拼接成一個字符串
#sep設置分隔符
df['col2'].str.cat(sep=',')
Out[67]: 'head,Body,FOOT'

#將兩列字符串拼接成一列字符串
#na_rep設置空值填充
df['col2'].str.cat(['d','e',np.nan],sep=',',na_rep='?')
Out[68]: 
0    head,d
1    Body,e
2    FOOT,?
Name: col2, dtype: object

#將兩列字符串拼接成一列字符串
#join設置鏈接方式
ss=pd.Series(['d','e','f'],index=[0,3,5])
df['col2'].str.cat(ss,sep=',',na_rep='?',join='left')
Out[69]: 
0    head,d
1    Body,?
2    FOOT,?
Name: col2, dtype: object

#將每一個元素上的字符串列表拼接
ss=pd.Series([['a','b'],['c','d']])
ss.str.join(',')
Out[72]: 
0    a,b
1    c,d
dtype: object
複製代碼

拆分

#拆分字符串並以列表做爲元素返回
#pat分隔符默認爲' ',可設置正則表達式用於分割
ss=pd.Series(['a,b,c','d,e'])
ss.str.split(pat=',')
Out[74]: 
0    [a, b, c]
1       [d, e]
dtype: object

#n限制分割的次數,expand設置是否將拆分後的字符串展開至列
ss.str.split(pat=',',n=1,expand=True)
Out[76]: 
   0    1
0  a  b,c
1  d    e
複製代碼

查找與替換

#是否包含
#pat可設置通常字符串或正則表達式
df['col2'].str.contains('a')
Out[89]: 
0     True
1    False
2    False
Name: col2, dtype: bool

#正則匹配
#pat只能設置正則表達式
#另有startswith,endswith方法可用於匹配開頭和結尾
#另有extract,extractall方法可用於抽取匹配的組
df['col2'].str.match('[a-z]*')
Out[90]: 
0    True
1    True
2    True
Name: col2, dtype: bool

#查找匹配並返回索引
#另有findall方法可查找所有匹配並以列表元素返回
#另有index方法可經過start,end設置查找範圍
df['col2'].str.find('d')
Out[91]: 
0    3
1    2
2   -1
Name: col2, dtype: int64

#統計指定模式出現次數
df['col2'].str.count('O')
Out[92]: 
0    0
1    0
2    2
Name: col2, dtype: int64

#替換
#第一個參數pat設置匹配模式,第二個參數repl設置用於替換的字符串
#參數n設置替換次數
#另有translate方法用於批量映射字符
df['col2'].str.replace('d','e')
Out[93]: 
0    heae
1    Boey
2    FOOT
Name: col2, dtype: object
複製代碼

刪除首尾字符

#另有lstrip,rstrip方法分別用於刪除首和尾的字符
df['col2'].str.strip('d')
Out[96]: 
0     hea
1    Body
2    FOOT
Name: col2, dtype: object

#可設置正則表達式
df['col2'].str.strip('[FT]')
Out[98]: 
0    head
1    Body
2      OO
Name: col2, dtype: object
複製代碼

2. 時間處理

(1). 時間類型

pd.Timestamp('2017-01-01 20:30:00',freq='D')
Out[80]: Timestamp('2017-01-01 20:30:00', freq='D')

pd.Period('2017-01-01 20:30')
Out[81]: Period('2017-01-01 20:30', 'T')

pd.Timedelta('2 days 1 hours')
Out[82]: Timedelta('2 days 01:00:00')

pd.Timedelta(1,unit='Y')
Out[83]: Timedelta('365 days 05:49:12')

from datetime import datetime
pd.Timestamp(datetime.now())
Out[84]: Timestamp('2019-05-18 16:14:26.691659')
複製代碼

pandas有兩種時間類型:TimestampPeriodTimestampdtypedatetime64PerioddtypeobjectTimestamp建立時能夠不指定時間頻率freq參數,但會致使沒法參與運算;Period則會根據輸入的值自動設置freq。可轉換datetime庫的時間類型。

Timedelta是時間變化量類型,第一個參數value指定變化量,輸入類型爲int時須要配合第二個參數unit(單位)使用,和時間類型中的freq是一個意思,默認'ns';也可輸入字符串類型,對應全部的拓展命名參數(days, seconds, microseconds,milliseconds, minutes, hours, weeks),可經過參數指定,或是以字符串形式聲明。

支持的freq取值有(按從大到小排列):‘Y’, ‘M’, ‘W’, ‘D’, ‘days’, ‘day’, ‘hours’, hour’, ‘hr’, ‘h’, ‘m’, ‘minute’, ‘min’, ‘minutes’, ‘T’, ‘S’, ‘seconds’, ‘sec’, ‘second’, ‘ms’, ‘milliseconds’, ‘millisecond’, ‘milli’, ‘millis’, ‘L’, ‘us’, ‘microseconds’, ‘microsecond’, ‘micro’, ‘micros’, ‘U’, ‘ns’, ‘nanoseconds’, ‘nano’, ‘nanos’, ‘nanosecond’, ‘N’。

(2). 時間範圍

生成

#時間範圍
tr=pd.date_range(start='2017-01-01',periods=5,freq='2H')

tr
Out[7]: 
DatetimeIndex(['2017-01-01 00:00:00', '2017-01-01 02:00:00',
               '2017-01-01 04:00:00', '2017-01-01 06:00:00',
               '2017-01-01 08:00:00'],
              dtype='datetime64[ns]', freq='2H')

#另外一種時間範圍
pr=pd.period_range(start='2017-01-01',periods=5,freq='D')

pr
Out[9]: 
PeriodIndex(['2017-01-01', '2017-01-02', '2017-01-03', '2017-01-04',
             '2017-01-05'],
            dtype='period[D]', freq='D')

#時間差範圍
tdr=pd.timedelta_range(start='1 day', end='2 days', freq='6H')

tdr
Out[11]: 
TimedeltaIndex(['1 days 00:00:00', '1 days 06:00:00', '1 days 12:00:00',
                '1 days 18:00:00', '2 days 00:00:00'],
               dtype='timedelta64[ns]', freq='6H')

#時間間隔範圍
ir=pd.interval_range(start=pd.Timestamp('2017-01-01'),periods=3, freq='MS')

ir
Out[31]: 
IntervalIndex([(2017-01-01, 2017-02-01], (2017-02-01, 2017-03-01], (2017-03-01, 2017-04-01]]
              closed='right',
              dtype='interval[datetime64[ns]]')
複製代碼

pd.date_rangepd.period_range用於時間範圍的生成,pd.timedelta_range用於時間變化量範圍的生成,pd.interval_range用於時間間隔範圍的生成。

以上方法有幾個相同功能的參數:
start參數指定範圍的開始;end參數指定範圍的結束;
periods參數指定生成的週期數(即數量);freq參數指定生成的頻率(即間隔);
name參數指定生成的索引名稱;closed參數指定區間閉合方式,支持的取值有'left''right'None(即兩邊都閉合),默認None

startendperiodsfreq這四個參數至少指定其中三個。

這些方法生成的都是索引類型,可經過.to_series().to_frame()轉換爲SerisDataFrame

變動

tr=pd.date_range(start='2017-01-01',periods=5,freq='2H')

#移動範圍
tr.shift(-1,freq='D')
Out[172]: 
DatetimeIndex(['2016-12-31 00:00:00', '2016-12-31 02:00:00',
               '2016-12-31 04:00:00', '2016-12-31 06:00:00',
               '2016-12-31 08:00:00'],
              dtype='datetime64[ns]', freq='2H')

ts=pd.Series(np.arange(len(tr)),index=tr)

#按指定頻率重採樣
ts.asfreq(freq='4H')
Out[175]: 
2017-01-01 00:00:00    0
2017-01-01 04:00:00    2
2017-01-01 08:00:00    4
Freq: 4H, dtype: int32
複製代碼

shift方法用於時間範圍的移動,第一個參數n指定移動量,第二個參數freq指定頻率。

asfreq方法用於按指定頻率重採樣,只能用於使用時間索引的SeriesDataFrame,第一個參數freq指定頻率,第二個參數method指定填充NaN的方式,當新採樣頻率不能被舊頻率整除時,會出現值爲NaN的無效採樣,可選'ffill'(前一個有效值)和'bfill'(後一個有效值),默認None(不填充)。

(3). 獲取時間部分

時間類型

t=pd.Timestamp('2017-01-02 20:30:40.50')

t.date()
Out[101]: datetime.date(2017, 1, 2)

t.year
Out[102]: 2017

t.month
Out[103]: 1

t.day
Out[104]: 2

t.time()
Out[105]: datetime.time(20, 30, 40, 500000)

t.hour
Out[106]: 20

t.minute
Out[107]: 30

t.second
Out[108]: 40

t.microsecond
Out[109]: 500000

t.quarter
Out[110]: 1

t.weekday()
Out[118]: 0

t.day_name()
Out[119]: 'Monday'

t.week
Out[120]: 1
複製代碼

時間類型的Series可調用.dt下的同名屬性,datetimeweekday方法都變爲以屬性形式訪問,day_name方法可經過weekday_name屬性訪問。

時間變化量類型

td=pd.Timedelta(weeks=0,days=1,hours=2,minutes=3,seconds=4,
                milliseconds=5,microseconds=6)

td.days
Out[141]: 1

td.seconds
Out[142]: 7384

td.microseconds
Out[143]: 5006

td.total_seconds()
Out[145]: 93784.005006
複製代碼

Timedeltatotal_seconds方法獲取總秒數;dayssecondsmicroseconds獲取各個部分,只分這三個,yearsmonthshoursminutes等是沒有的。

時間變化量類型的Series可調用.dt下的同名屬性或方法。

(4). 類型轉換

其餘類型轉時間

from datetime import datetime

t=pd.Timestamp(datetime.now())

p=pd.Period(t,freq='D')
複製代碼

建立單個時間類型時能夠直接傳入支持轉換的類型完成轉換。 Period必須指定freq

ss=pd.Series(['2017-01-01','2017-01-02'])

ss.astype('datetime64')
Out[183]: 
0   2017-01-01
1   2017-01-02
dtype: datetime64[ns]

pd.to_datetime(ss)
Out[184]: 
0   2017-01-01
1   2017-01-02
dtype: datetime64[ns]
複製代碼

SeriesDataFrameastype方法指定類型datetime64能夠轉換類型爲時間,靜態pd.to_datetime能夠完成等效轉換。

SeriesDataFrameto_periodto_timestamp方法是做用於索引而不是數據的,調用的是索引的同名方法,其中DatetimeIndexPeriodIndex是可經過這兩個方法相互轉換的。

時間轉字符串

tr=pd.date_range(start='2017-01-01',periods=5,freq='D')

tr.strftime('%Y-%m-%d,%a')
Out[231]: 
Index(['2017-01-01,Sun', '2017-01-02,Mon', '2017-01-03,Tue', '2017-01-04,Wed',
       '2017-01-05,Thu'],
      dtype='object')
複製代碼

Series類型可經過.dt下的同名方法調用轉換方法。

支持的轉換格式定義以下:

%y 年(兩位)
%Y 年(四位)
%m
%d
%H 時(24小時制)
%I 時(12小時制)
%M
%S

%j 年內第幾天
%p 上午或下午,AM或PM
%U 年內第幾周,週日爲一週的開始
%w 周,週日爲一週的開始
%W 年內第幾周,週一爲一週的開始

% %Y-%m-%d %H:%M:%S的簡寫形式
%F %Y-%m-%d的簡寫形式
%D %m/%d/%y的簡寫形式

%a 本地的周簡稱
%A 本地的周名稱
%b 本地的月簡稱
%B 本地的月名稱
%c 本地的日期表示和時間表示
%x 本地的日期表示
%X 本地的時間表示
%Z 當前時區的名稱
%% %號自己

(5). 時間運算

#標量值時間
pd.Period('2017-01-01 20:30:00',freq='D')+1
Out[253]: Period('2017-01-02', 'D')

ss1=pd.Series(['2017-01-01','2017-02-02'])
ss1=ss1.astype('datetime64')
ss2=pd.Series(['2017-01-05','2017-02-04'])
ss2=ss2.astype('datetime64')

#時間-時間
ss2-ss1
Out[255]: 
0   4 days
1   2 days
dtype: timedelta64[ns]

#獲取時間變化量的屬性
(ss2-ss1).dt.days
Out[256]: 
0    4
1    2
dtype: int64

#時間變化量縮放
(ss2-ss1)*2
Out[257]: 
0   8 days
1   4 days
dtype: timedelta64[ns]

#時間+時間變化量
ss1+pd.Timedelta(days=1)
Out[258]: 
0   2017-01-02
1   2017-02-03
dtype: datetime64[ns]
複製代碼

支持如下幾種運算:
時間 - 時間 = 時間變化量
時間變化量 + 時間變化量 = 時間變化量
時間變化量 * 整數 = 時間變化量
時間 + 時間變化量 = 時間
(時間:perioddatetime,時間變化量:timedelta,整數:int)

標量值的TimestampPeriod在設置了freq的狀況下能夠直接加減整數。

相關文章
相關標籤/搜索