【回爐重造】Python之Pandas詳細教程
- 前言
- 為什么要學習Pandas?
- 什么是Pandas?
- 1. Pandas的索引操作
- 1. Series和DataFrame中的索引都是Index物件
- 2. 索引物件不可變,保證了資料的安全
- 3. 常見的Index種類
- 3.1 Series索引
- 1. index 指定行索引名
- 2. 行索引
- 3. 切片索引
- 4. 不連續索引
- 5. 布爾索引
- 3.2 DataFrame索引
- 1. columns 指定列索引名
- 2. 列索引
- 3. 不連續索引
- 4. 高級索引:標簽、位置和混合
- 1. loc 標簽索引
- 2. iloc 位置索引
- 3. ix 標簽與位置混合索引
- 2. Pandas的對齊運算
- 2.1 Series的對齊運算
- 1. Series 按行、索引對齊
- 2. Series的對齊運算
- 2.2 DataFrame的對齊運算
- 1. DataFrame按行、列索引對齊
- 2. DataFrame的對齊運算
- 2.3 填充未對齊的資料進行運算
- fill\_value
- 3. Pandas的函式應用
- 3.1 apply 和 applymap
- 1. 可直接使用NumPy的函式
- 2. 通過apply將函式應用到列或行上
- 3. 通過applymap將函式應用到每個資料上
- 3.2 排序
- 1. 索引排序
- 2. 按值排序
- 3.3 處理缺失資料
- 1. 判斷是否存在缺失值:isnull\(\)
- 2. 丟棄缺失資料:dropna\(\)
- 3. 填充缺失資料:fillna\(\)
- 4. 層級索引(hierarchical indexing)
- 4.1 MultiIndex索引物件
- 4.2 選取子集
- 1. 外層選取:
- 2. 內層選取:
- 4.2 交換分層順序
- swaplevel\(\)
- 4.3 交換并排序分層
- sortlevel\(\)
- 5. Pandas統計計算和描述
- 5.1 常用的統計計算
- sum, mean, max, min…
- 5.2 常用的統計描述
- describe 產生多個統計資料
- 5.3 常用的統計描述方法
- 6. 資料讀取與存盤
- 6.1 csv檔案
- 6.2 資料庫互動
- 7. 資料清洗
- 7.1 資料清洗和準備
- 1. 處理缺失資料
- 2. 資料轉換
- 2.1 處理重復資料
- 2.2 duplicated\(\)是否為重復行
- 2.4 drop\_duplicates\(\)過濾重復行
- 2.5 利用函式或映射進行資料轉換
- 2.6 替換值
- replace根據值的內容進行替換
- 3. 字串操作
- 3.1 字串方法
- 3.2 正則運算式方法
- 3.3 pandas字串函式
- 7.2 資料合并
- 1. 資料合并\(pd.merge\)
- 1. 處理重復列名
- 2. 按索引連接
- 2. 資料合并\(pd.concat\)
- 1. NumPy的concat
- 2. pd.concat
- 7.3 重塑
- 1. stack
- 2. unstack
- 8. 資料分組聚合
- 8.1 聚合
- 9. Pandas中的時間序列
- 9.1 時間和日期資料型別及其工具
- 9.2 字串和datetime的相互轉換
- 時間序列基礎
- 9.3 索引、選取、子集構造
- 9.4 日期的范圍、頻率以及移動
- 生成日期范圍
- 重采樣及頻率轉換
前言

為什么要學習Pandas?
那么問題來了:
numpy已經能夠幫助我們處理資料,能夠結合matplotlib解決我們資料分析的問題,那么pandas學習的目的在什么地方呢?
numpy能夠幫我們處理處理數值型資料,但是這還不夠, 很多時候,我們的資料除了數值之外,還有字串,還有時間序列等
比如:我們通過爬蟲獲取到了存盤在資料庫中的資料
所以,pandas出現了,
什么是Pandas?
Pandas的名稱來自于面板資料(panel data)
Pandas是一個強大的分析結構化資料的工具集,基于NumPy構建,提供了高級資料結構和資料操作工具,它是使Python成為強大而高效的資料分析環境的重要因素之一,
-
一個強大的分析和操作大型結構化資料集所需的工具集
-
基礎是NumPy,提供了高性能矩陣的運算
-
提供了大量能夠快速便捷地處理資料的函式和方法
-
應用于資料挖掘,資料分析
-
提供資料清洗功能
官網
http://pandas.pydata.org/
1. Pandas的索引操作
索引物件Index
1. Series和DataFrame中的索引都是Index物件
示例代碼:
print(type(ser_obj.index))
print(type(df_obj2.index))
print(df_obj2.index)
運行結果:
<class 'pandas.indexes.range.RangeIndex'>
<class 'pandas.indexes.numeric.Int64Index'>
Int64Index([0, 1, 2, 3], dtype='int64')
2. 索引物件不可變,保證了資料的安全
示例代碼:
# 索引物件不可變
df_obj2.index[0] = 2
運行結果:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-23-7f40a356d7d1> in <module>()
1 # 索引物件不可變
----> 2 df_obj2.index[0] = 2
/Users/Power/anaconda/lib/python3.6/site-packages/pandas/indexes/base.py in __setitem__(self, key, value)
1402
1403 def __setitem__(self, key, value):
-> 1404 raise TypeError("Index does not support mutable operations")
1405
1406 def __getitem__(self, key):
TypeError: Index does not support mutable operations
3. 常見的Index種類
- Index,索引
- Int64Index,整數索引
- MultiIndex,層級索引
- DatetimeIndex,時間戳型別
3.1 Series索引
1. index 指定行索引名
示例代碼:
ser_obj = pd.Series(range(5), index = ['a', 'b', 'c', 'd', 'e'])
print(ser_obj.head())
運行結果:
a 0
b 1
c 2
d 3
e 4
dtype: int64
2. 行索引
ser_obj[‘label’], ser_obj[pos]
示例代碼:
# 行索引
print(ser_obj['b'])
print(ser_obj[2])
運行結果:
1
2
3. 切片索引
ser_obj[2:4], ser_obj[‘label1’: ’label3’]
注意,按索引名切片操作時,是包含終止索引的,
示例代碼:
# 切片索引
print(ser_obj[1:3])
print(ser_obj['b':'d'])
運行結果:
b 1
c 2
dtype: int64
b 1
c 2
d 3
dtype: int64
4. 不連續索引
ser_obj[[‘label1’, ’label2’, ‘label3’]]
示例代碼:
# 不連續索引
print(ser_obj[[0, 2, 4]])
print(ser_obj[['a', 'e']])
運行結果:
a 0
c 2
e 4
dtype: int64
a 0
e 4
dtype: int64
5. 布爾索引
示例代碼:
# 布爾索引
ser_bool = ser_obj > 2
print(ser_bool)
print(ser_obj[ser_bool])
print(ser_obj[ser_obj > 2])
運行結果:
a False
b False
c False
d True
e True
dtype: bool
d 3
e 4
dtype: int64
d 3
e 4
dtype: int64
3.2 DataFrame索引
1. columns 指定列索引名
示例代碼:
import numpy as np
df_obj = pd.DataFrame(np.random.randn(5,4), columns = ['a', 'b', 'c', 'd'])
print(df_obj.head())
運行結果:
a b c d
0 -0.241678 0.621589 0.843546 -0.383105
1 -0.526918 -0.485325 1.124420 -0.653144
2 -1.074163 0.939324 -0.309822 -0.209149
3 -0.716816 1.844654 -2.123637 -1.323484
4 0.368212 -0.910324 0.064703 0.486016

2. 列索引
df_obj[[‘label’]]
示例代碼:
# 列索引
print(df_obj['a']) # 回傳Series型別
運行結果:
0 -0.241678
1 -0.526918
2 -1.074163
3 -0.716816
4 0.368212
Name: a, dtype: float64
3. 不連續索引
df_obj[[‘label1’, ‘label2’]]
示例代碼:
# 不連續索引
print(df_obj[['a','c']])
運行結果:
a c
0 -0.241678 0.843546
1 -0.526918 1.124420
2 -1.074163 -0.309822
3 -0.716816 -2.123637
4 0.368212 0.064703
4. 高級索引:標簽、位置和混合
Pandas的高級索引有3種
1. loc 標簽索引
DataFrame 不能直接切片,可以通過loc來做切片
loc是基于標簽名的索引,也就是我們自定義的索引名
示例代碼:
# 標簽索引 loc
# Series
print(ser_obj['b':'d'])
print(ser_obj.loc['b':'d'])
# DataFrame
print(df_obj['a'])
# 第一個引數索引行,第二個引數是列
print(df_obj.loc[0:2, 'a'])
運行結果:
b 1
c 2
d 3
dtype: int64
b 1
c 2
d 3
dtype: int64
0 -0.241678
1 -0.526918
2 -1.074163
3 -0.716816
4 0.368212
Name: a, dtype: float64
0 -0.241678
1 -0.526918
2 -1.074163
Name: a, dtype: float64
2. iloc 位置索引
作用和loc一樣,不過是基于索引編號來索引
示例代碼:
# 整型位置索引 iloc
# Series
print(ser_obj[1:3])
print(ser_obj.iloc[1:3])
# DataFrame
print(df_obj.iloc[0:2, 0]) # 注意和df_obj.loc[0:2, 'a']的區別
運行結果:
b 1
c 2
dtype: int64
b 1
c 2
dtype: int64
0 -0.241678
1 -0.526918
Name: a, dtype: float64
3. ix 標簽與位置混合索引
ix是以上二者的綜合,既可以使用索引編號,又可以使用自定義索引,要視情況不同來使用,
如果索引既有數字又有英文,那么這種方式是不建議使用的,容易導致定位的混亂,
示例代碼:
# 混合索引 ix
# Series
print(ser_obj.ix[1:3])
print(ser_obj.ix['b':'c'])
# DataFrame
print(df_obj.loc[0:2, 'a'])
print(df_obj.ix[0:2, 0])
運行結果:
b 1
c 2
dtype: int64
b 1
c 2
dtype: int64
0 -0.241678
1 -0.526918
2 -1.074163
Name: a, dtype: float64
注意
DataFrame索引操作,可將其看作ndarray的索引操作
標簽的切片索引是包含末尾位置的
2. Pandas的對齊運算
Pandas的對齊運算是資料清洗的重要程序,可以按索引對齊進行運算,如果沒對齊的位置則補NaN,最后也可以填充NaN
2.1 Series的對齊運算
1. Series 按行、索引對齊
示例代碼:
s1 = pd.Series(range(10, 20), index = range(10))
s2 = pd.Series(range(20, 25), index = range(5))
print('s1: ' )
print(s1)
print('')
print('s2: ')
print(s2)
運行結果:
s1:
0 10
1 11
2 12
3 13
4 14
5 15
6 16
7 17
8 18
9 19
dtype: int64
s2:
0 20
1 21
2 22
3 23
4 24
dtype: int64
2. Series的對齊運算
示例代碼:
# Series 對齊運算
s1 + s2
運行結果:
0 30.0
1 32.0
2 34.0
3 36.0
4 38.0
5 NaN
6 NaN
7 NaN
8 NaN
9 NaN
dtype: float64
2.2 DataFrame的對齊運算
1. DataFrame按行、列索引對齊
示例代碼:
df1 = pd.DataFrame(np.ones((2,2)), columns = ['a', 'b'])
df2 = pd.DataFrame(np.ones((3,3)), columns = ['a', 'b', 'c'])
print('df1: ')
print(df1)
print('')
print('df2: ')
print(df2)
運行結果:
df1:
a b
0 1.0 1.0
1 1.0 1.0
df2:
a b c
0 1.0 1.0 1.0
1 1.0 1.0 1.0
2 1.0 1.0 1.0
2. DataFrame的對齊運算
示例代碼:
# DataFrame對齊操作
df1 + df2
運行結果:
a b c
0 2.0 2.0 NaN
1 2.0 2.0 NaN
2 NaN NaN NaN
2.3 填充未對齊的資料進行運算
fill_value
使用
add,sub,div,mul的同時,通過
fill_value指定填充值,未對齊的資料將和填充值做運算
示例代碼:
print(s1)
print(s2)
s1.add(s2, fill_value = -1)
print(df1)
print(df2)
df1.sub(df2, fill_value = 2.)
運行結果:
# print(s1)
0 10
1 11
2 12
3 13
4 14
5 15
6 16
7 17
8 18
9 19
dtype: int64
# print(s2)
0 20
1 21
2 22
3 23
4 24
dtype: int64
# s1.add(s2, fill_value = -1)
0 30.0
1 32.0
2 34.0
3 36.0
4 38.0
5 14.0
6 15.0
7 16.0
8 17.0
9 18.0
dtype: float64
# print(df1)
a b
0 1.0 1.0
1 1.0 1.0
# print(df2)
a b c
0 1.0 1.0 1.0
1 1.0 1.0 1.0
2 1.0 1.0 1.0
# df1.sub(df2, fill_value = 2.)
a b c
0 0.0 0.0 1.0
1 0.0 0.0 1.0
2 1.0 1.0 1.0
算術方法表:
| 方法 | 描述 |
|---|---|
| add,radd | 加法(+) |
| sub,rsub | 減法(-) |
| div,rdiv | 除法(/) |
| floordiv,rfllordiv | 整除(//) |
| mul,rmul | 乘法(*) |
| pow,rpow | 冪次方(**) |
3. Pandas的函式應用
3.1 apply 和 applymap
1. 可直接使用NumPy的函式
示例代碼:
# Numpy ufunc 函式
df = pd.DataFrame(np.random.randn(5,4) - 1)
print(df)
print(np.abs(df))
運行結果:
0 1 2 3
0 -0.062413 0.844813 -1.853721 -1.980717
1 -0.539628 -1.975173 -0.856597 -2.612406
2 -1.277081 -1.088457 -0.152189 0.530325
3 -1.356578 -1.996441 0.368822 -2.211478
4 -0.562777 0.518648 -2.007223 0.059411
0 1 2 3
0 0.062413 0.844813 1.853721 1.980717
1 0.539628 1.975173 0.856597 2.612406
2 1.277081 1.088457 0.152189 0.530325
3 1.356578 1.996441 0.368822 2.211478
4 0.562777 0.518648 2.007223 0.059411
2. 通過apply將函式應用到列或行上
示例代碼:
# 使用apply應用行或列資料
#f = lambda x : x.max()
print(df.apply(lambda x : x.max()))
運行結果:
0 -0.062413
1 0.844813
2 0.368822
3 0.530325
dtype: float64
注意指定軸的方向,默認axis=0,方向是列
示例代碼:
# 指定軸方向,axis=1,方向是行
print(df.apply(lambda x : x.max(), axis=1))
運行結果:
0 0.844813
1 -0.539628
2 0.530325
3 0.368822
4 0.518648
dtype: float64
3. 通過applymap將函式應用到每個資料上
示例代碼:
# 使用applymap應用到每個資料
f2 = lambda x : '%.2f' % x
print(df.applymap(f2))
運行結果:
0 1 2 3
0 -0.06 0.84 -1.85 -1.98
1 -0.54 -1.98 -0.86 -2.61
2 -1.28 -1.09 -0.15 0.53
3 -1.36 -2.00 0.37 -2.21
4 -0.56 0.52 -2.01 0.06
3.2 排序
1. 索引排序
sort_index()
排序默認使用升序排序,ascending=False 為降序排序
示例代碼:
# Series
s4 = pd.Series(range(10, 15), index = np.random.randint(5, size=5))
print(s4)
# 索引排序
s4.sort_index() # 0 0 1 3 3
運行結果:
0 10
3 11
1 12
3 13
0 14
dtype: int64
0 10
0 14
1 12
3 11
3 13
dtype: int64
對DataFrame操作時注意軸方向
示例代碼:
# DataFrame
df4 = pd.DataFrame(np.random.randn(3, 5),
index=np.random.randint(3, size=3),
columns=np.random.randint(5, size=5))
print(df4)
df4_isort = df4.sort_index(axis=1, ascending=False)
print(df4_isort) # 4 2 1 1 0
運行結果:
1 4 0 1 2
2 -0.416686 -0.161256 0.088802 -0.004294 1.164138
1 -0.671914 0.531256 0.303222 -0.509493 -0.342573
1 1.988321 -0.466987 2.787891 -1.105912 0.889082
4 2 1 1 0
2 -0.161256 1.164138 -0.416686 -0.004294 0.088802
1 0.531256 -0.342573 -0.671914 -0.509493 0.303222
1 -0.466987 0.889082 1.988321 -1.105912 2.787891
2. 按值排序
sort_values(by=‘column name’)
根據某個唯一的列名進行排序,如果有其他相同列名則報錯,
示例代碼:
# 按值排序
df4_vsort = df4.sort_values(by=0, ascending=False)
print(df4_vsort)
運行結果:
1 4 0 1 2
1 1.988321 -0.466987 2.787891 -1.105912 0.889082
1 -0.671914 0.531256 0.303222 -0.509493 -0.342573
2 -0.416686 -0.161256 0.088802 -0.004294 1.164138
3.3 處理缺失資料
示例代碼:
df_data = pd.DataFrame([np.random.randn(3), [1., 2., np.nan],
[np.nan, 4., np.nan], [1., 2., 3.]])
print(df_data.head())
運行結果:
0 1 2
0 -0.281885 -0.786572 0.487126
1 1.000000 2.000000 NaN
2 NaN 4.000000 NaN
3 1.000000 2.000000 3.000000
1. 判斷是否存在缺失值:isnull()
示例代碼:
# isnull
print(df_data.isnull())
運行結果:
0 1 2
0 False False False
1 False False True
2 True False True
3 False False False
2. 丟棄缺失資料:dropna()
根據axis軸方向,丟棄包含NaN的行或列, 示例代碼:
# dropna
print(df_data.dropna()) # 默認是按行
print(df_data.dropna(axis=1)) # axis=1是按列
運行結果:
0 1 2
0 -0.281885 -0.786572 0.487126
3 1.000000 2.000000 3.000000
1
0 -0.786572
1 2.000000
2 4.000000
3 2.000000
3. 填充缺失資料:fillna()
示例代碼:
# fillna
print(df_data.fillna(-100.))
運行結果:
0 1 2
0 -0.281885 -0.786572 0.487126
1 1.000000 2.000000 -100.000000
2 -100.000000 4.000000 -100.000000
3 1.000000 2.000000 3.000000
4. 層級索引(hierarchical indexing)
下面創建一個Series, 在輸入索引Index時,輸入了由兩個子list組成的list,第一個子list是外層索引,第二個list是內層索引,
示例代碼:
import pandas as pd
import numpy as np
ser_obj = pd.Series(np.random.randn(12),index=[
['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'd'],
[0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2]
])
print(ser_obj)
運行結果:
a 0 0.099174
1 -0.310414
2 -0.558047
b 0 1.742445
1 1.152924
2 -0.725332
c 0 -0.150638
1 0.251660
2 0.063387
d 0 1.080605
1 0.567547
2 -0.154148
dtype: float64
4.1 MultiIndex索引物件
-
列印這個Series的索引型別,顯示是MultiIndex
-
直接將索引列印出來,可以看到有lavels,和labels兩個資訊,levels表示兩個層級中分別有那些標簽,labels是每個位置分別是什么標簽,
示例代碼:
print(type(ser_obj.index))
print(ser_obj.index)
運行結果:
<class 'pandas.indexes.multi.MultiIndex'>
MultiIndex(levels=[['a', 'b', 'c', 'd'], [0, 1, 2]],
labels=[[0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3], [0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2]])
4.2 選取子集
-
根據索引獲取資料,因為現在有兩層索引,當通過外層索引獲取資料的時候,可以直接利用外層索引的標簽來獲取,
-
當要通過內層索引獲取資料的時候,在list中傳入兩個元素,前者是表示要選取的外層索引,后者表示要選取的內層索引,
1. 外層選取:
ser_obj[‘outer_label’]
示例代碼:
# 外層選取
print(ser_obj['c'])
運行結果:
0 -1.362096
1 1.558091
2 -0.452313
dtype: float64
2. 內層選取:
ser_obj[:, ‘inner_label’]
示例代碼:
# 內層選取
print(ser_obj[:, 2])
運行結果:
a 0.826662
b 0.015426
c -0.452313
d -0.051063
dtype: float64
常用于分組操作、透視表的生成等
4.2 交換分層順序
swaplevel()
.swaplevel( )交換內層與外層索引,
示例代碼:
print(ser_obj.swaplevel())
運行結果:
0 a 0.099174
1 a -0.310414
2 a -0.558047
0 b 1.742445
1 b 1.152924
2 b -0.725332
0 c -0.150638
1 c 0.251660
2 c 0.063387
0 d 1.080605
1 d 0.567547
2 d -0.154148
dtype: float64
4.3 交換并排序分層
sortlevel()
.sortlevel( )先對外層索引進行排序,再對內層索引進行排序,默認是升序,
示例代碼:
# 交換并排序分層
print(ser_obj.swaplevel().sortlevel())
運行結果:
0 a 0.099174
b 1.742445
c -0.150638
d 1.080605
1 a -0.310414
b 1.152924
c 0.251660
d 0.567547
2 a -0.558047
b -0.725332
c 0.063387
d -0.154148
dtype: float64
5. Pandas統計計算和描述
示例代碼:
arr1 = np.random.rand(4,3)
pd1 = pd.DataFrame(arr1,columns=list('ABC'),index=list('abcd'))
f = lambda x: '%.2f'% x
pd2 = pd1.applymap(f).astype(float)
pd2
運行結果:
A B C
a 0.87 0.26 0.67
b 0.69 0.89 0.17
c 0.94 0.33 0.04
d 0.35 0.46 0.29
5.1 常用的統計計算
sum, mean, max, min…
axis=0 按列統計,axis=1按行統計
skipna 排除缺失值, 默認為True
示例代碼:
pd2.sum() #默認把這一列的Series計算,所有行求和
pd2.sum(axis='columns') #指定求每一行的所有列的和
pd2.idxmax()#查看每一列所有行的最大值所在的標簽索引,同樣我們也可以通過axis='columns'求每一行所有列的最大值的標簽索引
運行結果:
A 2.85
B 1.94
C 1.17
dtype: float64
a 1.80
b 1.75
c 1.31
d 1.10
dtype: float64
A c
B b
C a
dtype: object

5.2 常用的統計描述
describe 產生多個統計資料
示例代碼:
pd2.describe()#查看匯總
運行結果:
A B C
count 4.000000 4.00000 4.000000
mean 0.712500 0.48500 0.292500
std 0.263613 0.28243 0.271585
min 0.350000 0.26000 0.040000
25% 0.605000 0.31250 0.137500
50% 0.780000 0.39500 0.230000
75% 0.887500 0.56750 0.385000
max 0.940000 0.89000 0.670000
#百分比:除以原來的量
pd2.pct_change() #查看行的百分比變化,同樣指定axis='columns'列與列的百分比變化
A B C
a NaN NaN NaN
b -0.206897 2.423077 -0.746269
c 0.362319 -0.629213 -0.764706
d -0.627660 0.393939 6.250000
5.3 常用的統計描述方法

6. 資料讀取與存盤


6.1 csv檔案
-
讀取csv檔案
read_csv(file_path or buf,usecols,encoding):file_path:檔案路徑,usecols:指定讀取的列名,encoding:編碼data = pd.read_csv('d:/test_data/food_rank.csv',encoding='utf8') data.head() name num 0 酥油茶 219.0 1 青稞酒 95.0 2 酸奶 62.0 3 糌粑 16.0 4 琵琶肉 2.0 #指定讀取的列名 data = pd.read_csv('d:/test_data/food_rank.csv',usecols=['name']) data.head() name 0 酥油茶 1 青稞酒 2 酸奶 3 糌粑 4 琵琶肉 #如果檔案路徑有中文,則需要知道引數engine='python' data = pd.read_csv('d:/資料/food_rank.csv',engine='python',encoding='utf8') data.head() name num 0 酥油茶 219.0 1 青稞酒 95.0 2 酸奶 62.0 3 糌粑 16.0 4 琵琶肉 2.0 #建議檔案路徑和檔案名,不要出現中文 -
寫入csv檔案
DataFrame:
to_csv(file_path or buf,sep,columns,header,index,na_rep,mode):file_path:保存檔案路徑,默認None,sep:分隔符,默認’,’ ,columns:是否保留某列資料,默認None,header:是否保留列名,默認True,index:是否保留行索引,默認True,na_rep:指定字串來代替空值,默認是空字符,mode:默認’w’,追加’a’
**Series**:`Series.to_csv`\
(_path=None_,_index=True_,_sep='_,_'_,_na\_rep=''_,_header=False_,_mode='w'_,_encoding=None_\)
6.2 資料庫互動
- pandas
- sqlalchemy
- pymysql
# 匯入必要模塊
import pandas as pd
from sqlalchemy import create_engine
#初始化資料庫連接
#用戶名root 密碼 埠 3306 資料庫 db2
engine = create_engine('mysql+pymysql://root:@localhost:3306/db2')
#查詢陳述句
sql = '''
select * from class;
'''
#兩個引數 sql陳述句 資料庫連接
df = pd.read_sql(sql,engine)
df

#新建
df = pd.DataFrame({'id':[1,2,3,4],'num':[34,56,78,90]})
df = pd.read_csv('ex1.csv')
# #寫入到資料庫
df.to_sql('df2',engine,index=False)
print("ok")
進入資料庫查看

7. 資料清洗
7.1 資料清洗和準備
資料清洗是資料分析關鍵的一步,直接影響之后的處理作業
資料需要修改嗎?有什么需要修改的嗎?資料應該怎么調整才能適用于接下來的分析和挖掘?
是一個迭代的程序,實際專案中可能需要不止一次地執行這些清洗操作
1. 處理缺失資料
- pd.fillna()
- pd.dropna()

2. 資料轉換
2.1 處理重復資料
2.2 duplicated()是否為重復行
duplicated\(\): 回傳布爾型Series表示每行是否為重復行
示例代碼:
import numpy as np
import pandas as pd
df_obj = pd.DataFrame({'data1' : ['a'] * 4 + ['b'] * 4,
'data2' : np.random.randint(0, 4, 8)})
print(df_obj)
print(df_obj.duplicated())
運行結果:
# print(df_obj)
data1 data2
0 a 3
1 a 2
2 a 3
3 a 3
4 b 1
5 b 0
6 b 3
7 b 0
# print(df_obj.duplicated())
0 False
1 False
2 True
3 True
4 False
5 False
6 False
7 True
dtype: bool
2.4 drop_duplicates()過濾重復行
- 默認判斷全部列
- 可指定按某些列判斷
示例代碼:
print(df_obj.drop_duplicates())
print(df_obj.drop_duplicates('data2'))
運行結果:
# print(df_obj.drop_duplicates())
data1 data2
0 a 3
1 a 2
4 b 1
5 b 0
6 b 3
# print(df_obj.drop_duplicates('data2'))
data1 data2
0 a 3
1 a 2
4 b 1
5 b 0
2.5 利用函式或映射進行資料轉換
根據map傳入的函式對每行或每列進行轉換
示例代碼:
ser_obj = pd.Series(np.random.randint(0,10,10))
print(ser_obj)
print(ser_obj.map(lambda x : x ** 2))
運行結果:
# print(ser_obj)
0 1
1 4
2 8
3 6
4 8
5 6
6 6
7 4
8 7
9 3
dtype: int64
# print(ser_obj.map(lambda x : x ** 2))
0 1
1 16
2 64
3 36
4 64
5 36
6 36
7 16
8 49
9 9
dtype: int64
2.6 替換值
replace根據值的內容進行替換
示例代碼:
# 單個值替換單個值
print(ser_obj.replace(1, -100))
# 多個值替換一個值
print(ser_obj.replace([6, 8], -100))
# 多個值替換多個值
print(ser_obj.replace([4, 7], [-100, -200]))
運行結果:
# print(ser_obj.replace(1, -100))
0 -100
1 4
2 8
3 6
4 8
5 6
6 6
7 4
8 7
9 3
dtype: int64
# print(ser_obj.replace([6, 8], -100))
0 1
1 4
2 -100
3 -100
4 -100
5 -100
6 -100
7 4
8 7
9 3
dtype: int64
# print(ser_obj.replace([4, 7], [-100, -200]))
0 1
1 -100
2 8
3 6
4 8
5 6
6 6
7 -100
8 -200
9 3
dtype: int64
3. 字串操作
3.1 字串方法


3.2 正則運算式方法

3.3 pandas字串函式

7.2 資料合并
1. 資料合并(pd.merge)
-
根據單個或多個鍵將不同DataFrame的行連接起來
-
類似資料庫的連接操作
-
pd.merge:(left, right, how=‘inner’,on=None,left_on=None, right_on=None )
left:合并時左邊的DataFrame
right:合并時右邊的DataFrame
how:合并的方式,默認’inner’, ‘outer’, ‘left’, ‘right’
on:需要合并的列名,必須兩邊都有的列名,并以 left 和 right 中的列名的交集作為連接鍵
left_on: left Dataframe中用作連接鍵的列
right_on: right Dataframe中用作連接鍵的列
-
內連接 inner:對兩張表都有的鍵的交集進行聯合

- 全連接 outer:對兩者表的都有的鍵的并集進行聯合

- 左連接 left:對所有左表的鍵進行聯合

- 右連接 right:對所有右表的鍵進行聯合

示例代碼:
import pandas as pd
import numpy as np
left = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
right = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
pd.merge(left,right,on='key') #指定連接鍵key
運行結果:
key A B C D
0 K0 A0 B0 C0 D0
1 K1 A1 B1 C1 D1
2 K2 A2 B2 C2 D2
3 K3 A3 B3 C3 D3

示例代碼:
left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
'key2': ['K0', 'K1', 'K0', 'K1'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
'key2': ['K0', 'K0', 'K0', 'K0'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
pd.merge(left,right,on=['key1','key2']) #指定多個鍵,進行合并
運行結果:
key1 key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K1 K0 A2 B2 C1 D1
2 K1 K0 A2 B2 C2 D2

#指定左連接
left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
'key2': ['K0', 'K1', 'K0', 'K1'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
'key2': ['K0', 'K0', 'K0', 'K0'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
pd.merge(left, right, how='left', on=['key1', 'key2'])
key1 key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K0 K1 A1 B1 NaN NaN
2 K1 K0 A2 B2 C1 D1
3 K1 K0 A2 B2 C2 D2
4 K2 K1 A3 B3 NaN NaN

#指定右連接
left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
'key2': ['K0', 'K1', 'K0', 'K1'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
'key2': ['K0', 'K0', 'K0', 'K0'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
pd.merge(left, right, how='right', on=['key1', 'key2'])
key1 key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K1 K0 A2 B2 C1 D1
2 K1 K0 A2 B2 C2 D2
3 K2 K0 NaN NaN C3 D3

默認是“內連接”(inner),即結果中的鍵是交集
how: 指定連接方式
“外連接”(outer),結果中的鍵是并集
示例代碼:
left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
'key2': ['K0', 'K1', 'K0', 'K1'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
'key2': ['K0', 'K0', 'K0', 'K0'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
pd.merge(left,right,how='outer',on=['key1','key2'])
運行結果:
key1 key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K0 K1 A1 B1 NaN NaN
2 K1 K0 A2 B2 C1 D1
3 K1 K0 A2 B2 C2 D2
4 K2 K1 A3 B3 NaN NaN
5 K2 K0 NaN NaN C3 D3

1. 處理重復列名
引數suffixes:默認為_x, _y
示例代碼:
# 處理重復列名
df_obj1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
'data' : np.random.randint(0,10,7)})
df_obj2 = pd.DataFrame({'key': ['a', 'b', 'd'],
'data' : np.random.randint(0,10,3)})
print(pd.merge(df_obj1, df_obj2, on='key', suffixes=('_left', '_right')))
運行結果:
data_left key data_right
0 9 b 1
1 5 b 1
2 1 b 1
3 2 a 8
4 2 a 8
5 5 a 8
2. 按索引連接
引數left_index=True或right_index=True
示例代碼:
# 按索引連接
df_obj1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
'data1' : np.random.randint(0,10,7)})
df_obj2 = pd.DataFrame({'data2' : np.random.randint(0,10,3)}, index=['a', 'b', 'd'])
print(pd.merge(df_obj1, df_obj2, left_on='key', right_index=True))
運行結果:
data1 key data2
0 3 b 6
1 4 b 6
6 8 b 6
2 6 a 0
4 3 a 0
5 0 a 0
2. 資料合并(pd.concat)
沿軸方向將多個物件合并到一起
1. NumPy的concat
np.concatenate
示例代碼:
import numpy as np
import pandas as pd
arr1 = np.random.randint(0, 10, (3, 4))
arr2 = np.random.randint(0, 10, (3, 4))
print(arr1)
print(arr2)
print(np.concatenate([arr1, arr2])) # 默認axis=0,按行拼接
print(np.concatenate([arr1, arr2], axis=1)) # 按列拼接
運行結果:
# print(arr1)
[[3 3 0 8]
[2 0 3 1]
[4 8 8 2]]
# print(arr2)
[[6 8 7 3]
[1 6 8 7]
[1 4 7 1]]
# print(np.concatenate([arr1, arr2]))
[[3 3 0 8]
[2 0 3 1]
[4 8 8 2]
[6 8 7 3]
[1 6 8 7]
[1 4 7 1]]
# print(np.concatenate([arr1, arr2], axis=1))
[[3 3 0 8 6 8 7 3]
[2 0 3 1 1 6 8 7]
[4 8 8 2 1 4 7 1]]
2. pd.concat
-
注意指定軸方向,默認axis=0
-
join指定合并方式,默認為outer
-
Series合并時查看行索引有無重復
df1 = pd.DataFrame(np.arange(6).reshape(3,2),index=list('abc'),columns=['one','two'])
df2 = pd.DataFrame(np.arange(4).reshape(2,2)+5,index=list('ac'),columns=['three','four'])
pd.concat([df1,df2]) #默認外連接,axis=0
four one three two
a NaN 0.0 NaN 1.0
b NaN 2.0 NaN 3.0
c NaN 4.0 NaN 5.0
a 6.0 NaN 5.0 NaN
c 8.0 NaN 7.0 NaN
pd.concat([df1,df2],axis='columns') #指定axis=1連接
one two three four
a 0 1 5.0 6.0
b 2 3 NaN NaN
c 4 5 7.0 8.0
#同樣我們也可以指定連接的方式為inner
pd.concat([df1,df2],axis=1,join='inner')
one two three four
a 0 1 5 6
c 4 5 7 8
7.3 重塑
1. stack
-
將列索引旋轉為行索引,完成層級索引
-
DataFrame->Series
示例代碼:
import numpy as np
import pandas as pd
df_obj = pd.DataFrame(np.random.randint(0,10, (5,2)), columns=['data1', 'data2'])
print(df_obj)
stacked = df_obj.stack()
print(stacked)
運行結果:
# print(df_obj)
data1 data2
0 7 9
1 7 8
2 8 9
3 4 1
4 1 2
# print(stacked)
0 data1 7
data2 9
1 data1 7
data2 8
2 data1 8
data2 9
3 data1 4
data2 1
4 data1 1
data2 2
dtype: int64
2. unstack
-
將層級索引展開
-
Series->DataFrame
-
默認操作內層索引,即level=-1
示例代碼:
# 默認操作內層索引
print(stacked.unstack())
# 通過level指定操作索引的級別
print(stacked.unstack(level=0))
運行結果:
# print(stacked.unstack())
data1 data2
0 7 9
1 7 8
2 8 9
3 4 1
4 1 2
# print(stacked.unstack(level=0))
0 1 2 3 4
data1 7 7 8 4 1
data2 9 8 9 1 2
8. 資料分組聚合
- 什么是分組聚合?如圖:

- groupby:(by=None,as_index=True)
-
by:根據什么進行分組,用于確定groupby的組
-
as_index:對于聚合輸出,回傳以組便簽為索引的物件,僅對DataFrame
df1 = pd.DataFrame({'fruit':['apple','banana','orange','apple','banana'],
'color':['red','yellow','yellow','cyan','cyan'],
'price':[8.5,6.8,5.6,7.8,6.4]})
#查看型別
type(df1.groupby('fruit'))
pandas.core.groupby.groupby.DataFrameGroupBy #GruopBy物件,它是一個包含組名,和資料塊的2維元組序列,支持迭代
for name, group in df1.groupby('fruit'):
print(name) #輸出組名
apple
banana
orange
print(group) # 輸出資料塊
fruit color price
0 apple red 8.5
3 apple cyan 7.8
fruit color price
1 banana yellow 6.8
4 banana cyan 6.4
fruit color price
2 orange yellow 5.6
#輸出group型別
print(type(group)) #資料塊是dataframe型別
<class 'pandas.core.frame.DataFrame'>
<class 'pandas.core.frame.DataFrame'>
<class 'pandas.core.frame.DataFrame'>
#選擇任意的資料塊
dict(list(df1.groupby('fruit')))['apple'] #取出apple組的資料塊
fruit color price
0 apple red 8.5
3 apple cyan 7.8
8.1 聚合
| 函式名 | 描述 |
|---|---|
| count | 分組中非NA值的數量 |
| sum | 非NA值的和 |
| mean | 非NA值的平均值 |
| median | 非NA值的中位數 |
| std, var | 標準差和方差 |
| min, max | 非NA的最小值,最大值 |
| prod | 非NA值的乘積 |
| first, last | 非NA值的第一個,最后一個 |
#Groupby物件具有上表中的聚合方法
#根據fruit來求price的平均值
df1['price'].groupby(df1['fruit']).mean()
fruit
apple 8.15
banana 6.60
orange 5.60
Name: price, dtype: float64
#或者
df1.groupby('fruit')['price'].mean()
# as_index=False(不把分組后的值作為索引,重新生成默認索引)
df1.groupby('fruit',as_index=False)['price'].mean()
fruit price
0 apple 8.15
1 banana 6.60
2 orange 5.60
"""
如果我現在有個需求,計算每種水果的差值,
1.上表中的聚合函式不能滿足于我們的需求,我們需要使用自定義的聚合函式
2.在分組物件中,使用我們自定義的聚合函式
"""
#定義一個計算差值的函式
def diff_value(arr):
return arr.max() - arr.min()
#使用自定義聚合函式,我們需要將函式傳遞給agg或aggregate方法,我們使用自定義聚合函式時,會比我們表中的聚合函式慢的多,因為要進行函式呼叫,資料重新排列
df1.groupby('fruit')['price'].agg(diff_value)
fruit
apple 0.7
banana 0.4
orange 0.0
Name: price, dtype: float64
9. Pandas中的時間序列
時間序列(time series)資料是一種重要的結構化資料形式,
在多個時間點觀察或測量到的任何時間都可以形成一段時間序列,很多時間, 時間序列是固定頻率的, 也就是說, 資料點是根據某種規律定期出現的(比如每15秒…),
時間序列也可以是不定期的,時間序列資料的意義取決于具體的應用場景,
主要由以下幾種:
- 時間戳(timestamp),特定的時刻,
- 固定時期(period),如2007年1月或2010年全年,
- 時間間隔(interval),由起始和結束時間戳表示,時期(period)可以被看做間隔(interval)的特例,
9.1 時間和日期資料型別及其工具
Python標準庫包含用于日期(date)和時間(time)資料的資料型別,而且還有日歷方面的功能,我們主要會用到datetime、time以及calendar模塊,
datetime.datetime(也可以簡寫為datetime)是用得最多的資料型別:
In [10]: from datetime import datetime
In [11]: now = datetime.now()
In [12]: now
Out[12]: datetime.datetime(2017, 9, 25, 14, 5, 52, 72973)
In [13]: now.year, now.month, now.day
Out[13]: (2017, 9, 25)
datetime以毫秒形式存盤日期和時間,timedelta表示兩個datetime物件之間的時間差:
In [14]: delta = datetime(2011, 1, 7) - datetime(2008, 6, 24, 8, 15)
In [15]: delta
Out[15]: datetime.timedelta(926, 56700)
In [16]: delta.days
Out[16]: 926
In [17]: delta.seconds
Out[17]: 56700
可以給datetime物件加上(或減去)一個或多個timedelta,這樣會產生一個新物件:
In [18]: from datetime import timedelta
In [19]: start = datetime(2011, 1, 7)
In [20]: start + timedelta(12)
Out[20]: datetime.datetime(2011, 1, 19, 0, 0)
In [21]: start - 2 * timedelta(12)
Out[21]: datetime.datetime(2010, 12, 14, 0, 0)

9.2 字串和datetime的相互轉換
利用str或strftime方法(傳入一個格式化字串),datetime物件和pandas的Timestamp物件(稍后就會介紹)可以被格式化為字串:
In [22]: stamp = datetime(2011, 1, 3)
In [23]: str(stamp)
Out[23]: '2011-01-03 00:00:00'
In [24]: stamp.strftime('%Y-%m-%d')
Out[24]: '2011-01-03'

datetime.strptime可以用這些格式化編碼將字串轉換為日期:
In [26]: datetime.strptime(value, '%Y-%m-%d')
Out[26]: datetime.datetime(2011, 1, 3, 0, 0)
In [27]: datestrs = ['7/6/2011', '8/6/2011']
In [28]: [datetime.strptime(x, '%m/%d/%Y') for x in datestrs]
Out[28]:
[datetime.datetime(2011, 7, 6, 0, 0),
datetime.datetime(2011, 8, 6, 0, 0)]
datetime.strptime是通過已知格式進行日期決議的最佳方式,但是每次都要撰寫格式定義是很麻煩的事情,尤其是對于一些常見的日期格式,
這種情況下,你可以用dateutil這個第三方包中的parser.parse方法(pandas中已經自動安裝好了):
In [29]: from dateutil.parser import parse
In [30]: parse('2011-01-03')
Out[30]: datetime.datetime(2011, 1, 3, 0, 0)
dateutil可以決議幾乎所有人類能夠理解的日期表示形式:
In [31]: parse('Jan 31, 1997 10:45 PM')
Out[31]: datetime.datetime(1997, 1, 31, 22, 45)
在國際通用的格式中,日出現在月的前面很普遍,傳入dayfirst=True即可解決這個問題:
In [32]: parse('6/12/2011', dayfirst=True)
Out[32]: datetime.datetime(2011, 12, 6, 0, 0)
Pandas通常是用于處理成組日期的,不管這些日期是DataFrame的軸索引還是列,to_datetime方法可以決議多種不同的日期表示形式,對標準日期格式(如ISO8601)的決議非常快:
In [33]: datestrs = ['2011-07-06 12:00:00', '2011-08-06 00:00:00']
In [34]: pd.to_datetime(datestrs)
Out[34]: DatetimeIndex(['2011-07-06 12:00:00', '2011-08-06 00:00:00'], dtype='datetime64[ns]', freq=None)
它還可以處理缺失值(None、空字串等):
In [35]: idx = pd.to_datetime(datestrs + [None])
In [36]: idx
Out[36]: DatetimeIndex(['2011-07-06 12:00:00', '2011-08-06 00:00:00', 'NaT'], dty
pe='datetime64[ns]', freq=None)
In [37]: idx[2]
Out[37]: NaT
In [38]: pd.isnull(idx)
Out[38]: array([False, False, True], dtype=bool)
NaT(Not a Time)是Pandas中時間戳資料的null值,
時間序列基礎
pandas最基本的時間序列型別就是以時間戳(通常以Python字串或datatime物件表示)為索引的Series:
In [39]: from datetime import datetime
In [40]: dates = [datetime(2011, 1, 2), datetime(2011, 1, 5),
....: datetime(2011, 1, 7), datetime(2011, 1, 8),
....: datetime(2011, 1, 10), datetime(2011, 1, 12)]
In [41]: ts = pd.Series(np.random.randn(6), index=dates)
In [42]: ts
Out[42]:
2011-01-02 -0.204708
2011-01-05 0.478943
2011-01-07 -0.519439
2011-01-08 -0.555730
2011-01-10 1.965781
2011-01-12 1.393406
dtype: float64
這些datetime物件實際上是被放在一個DatetimeIndex中的:
In [43]: ts.index
Out[43]:
DatetimeIndex(['2011-01-02', '2011-01-05', '2011-01-07', '2011-01-08',
'2011-01-10', '2011-01-12'],
dtype='datetime64[ns]', freq=None)
跟其他Series一樣,不同索引的時間序列之間的算術運算會自動按日期對齊:
In [44]: ts + ts[::2]
Out[44]:
2011-01-02 -0.409415
2011-01-05 NaN
2011-01-07 -1.038877
2011-01-08 NaN
2011-01-10 3.931561
2011-01-12 NaN
dtype: float64
ts[::2] 是每隔兩個取一個,
9.3 索引、選取、子集構造
當你根據標簽索引選取資料時,時間序列和其它的pandas.Series很像:
In [48]: stamp = ts.index[2]
In [49]: ts[stamp]
Out[49]: -0.51943871505673811
還有一種更為方便的用法:傳入一個可以被解釋為日期的字串:
In [50]: ts['1/10/2011']
Out[50]: 1.9657805725027142
In [51]: ts['20110110']
Out[51]: 1.9657805725027142
9.4 日期的范圍、頻率以及移動
Pandas中的原生時間序列一般被認為是不規則的,也就是說,它們沒有固定的頻率,對于大部分應用程式而言,這是無所謂的,但是,它常常需要以某種相對固定的頻率進行分析,比如每日、每月、每15分鐘等(這樣自然會在時間序列中引入缺失值),
幸運的是,pandas有一整套標準時間序列頻率以及用于重采樣、頻率推斷、生成固定頻率日期范圍的工具,
例如,我們可以將之前那個時間序列轉換為一個具有固定頻率(每日)的時間序列,只需呼叫resample即可:
In [72]: ts
Out[72]:
2011-01-02 -0.204708
2011-01-05 0.478943
2011-01-07 -0.519439
2011-01-08 -0.555730
2011-01-10 1.965781
2011-01-12 1.393406
dtype: float64
In [73]: resampler = ts.resample('D')
字串“D”是每天的意思,
頻率的轉換(或重采樣)是一個比較大的主題,這里,我將告訴你如何使用基本的頻率和它的倍數,
生成日期范圍
雖然我之前用的時候沒有明說,但你可能已經猜到pandas.date_range可用于根據指定的頻率生成指定長度的 DatetimeIndex:
In [74]: index = pd.date_range('2012-04-01', '2012-06-01')
In [75]: index
Out[75]:
DatetimeIndex(['2012-04-01', '2012-04-02', '2012-04-03', '2012-04-04',
'2012-04-05', '2012-04-06', '2012-04-07', '2012-04-08',
'2012-04-09', '2012-04-10', '2012-04-11', '2012-04-12',
'2012-04-13', '2012-04-14', '2012-04-15', '2012-04-16',
'2012-04-17', '2012-04-18', '2012-04-19', '2012-04-20',
'2012-04-21', '2012-04-22', '2012-04-23', '2012-04-24',
'2012-04-25', '2012-04-26', '2012-04-27', '2012-04-28',
'2012-04-29', '2012-04-30', '2012-05-01', '2012-05-02',
'2012-05-03', '2012-05-04', '2012-05-05', '2012-05-06',
'2012-05-07', '2012-05-08', '2012-05-09', '2012-05-10',
'2012-05-11', '2012-05-12', '2012-05-13', '2012-05-14',
'2012-05-15', '2012-05-16', '2012-05-17', '2012-05-18',
'2012-05-19', '2012-05-20', '2012-05-21', '2012-05-22',
'2012-05-23', '2012-05-24', '2012-05-25', '2012-05-26',
'2012-05-27', '2012-05-28', '2012-05-29', '2012-05-30',
'2012-05-31', '2012-06-01'],
dtype='datetime64[ns]', freq='D')
默認情況下,date_range會產生按天計算的時間點,如果只傳入起始或結束日期,那就還得傳入一個表示一段時間的數字:
In [76]: pd.date_range(start='2012-04-01', periods=20)
Out[76]:
DatetimeIndex(['2012-04-01', '2012-04-02', '2012-04-03', '2012-04-04',
'2012-04-05', '2012-04-06', '2012-04-07', '2012-04-08',
'2012-04-09', '2012-04-10', '2012-04-11', '2012-04-12',
'2012-04-13', '2012-04-14', '2012-04-15', '2012-04-16',
'2012-04-17', '2012-04-18', '2012-04-19', '2012-04-20'],
dtype='datetime64[ns]', freq='D')
In [77]: pd.date_range(end='2012-06-01', periods=20)
Out[77]:
DatetimeIndex(['2012-05-13', '2012-05-14', '2012-05-15', '2012-05-16',
'2012-05-17', '2012-05-18', '2012-05-19', '2012-05-20',
'2012-05-21', '2012-05-22', '2012-05-23', '2012-05-24',
'2012-05-25', '2012-05-26', '2012-05-27','2012-05-28',
'2012-05-29', '2012-05-30', '2012-05-31', '2012-06-01'],
dtype='datetime64[ns]', freq='D')
起始和結束日期定義了日期索引的嚴格邊界,
例如,如果你想要生成一個由每月最后一個作業日組成的日期索引,可以傳入"BM"頻率(表示business end of month),這樣就只會包含時間間隔內(或剛好在邊界上的)符合頻率要求的日期:
In [78]: pd.date_range('2000-01-01', '2000-12-01', freq='BM')
Out[78]:
DatetimeIndex(['2000-01-31', '2000-02-29', '2000-03-31', '2000-04-28',
'2000-05-31', '2000-06-30', '2000-07-31', '2000-08-31',
'2000-09-29', '2000-10-31', '2000-11-30'],
dtype='datetime64[ns]', freq='BM')

重采樣及頻率轉換
重采樣(resampling)指的是將時間序列從一個頻率轉換到另一個頻率的處理程序,
將高頻率資料聚合到低頻率稱為降采樣(downsampling),而將低頻率資料轉換到高頻率則稱為升采樣(upsampling),并不是所有的重采樣都能被劃分到這兩個大類中,
例如,將W-WED(每周三)轉換為W-FRI既不是降采樣也不是升采樣,
Pandas物件都帶有一個resample方法,它是各種頻率轉換作業的主力函式,resample有一個類似于groupby的API,呼叫resample可以分組資料,然后會呼叫一個聚合函式:
In [208]: rng = pd.date_range('2000-01-01', periods=100, freq='D')
In [209]: ts = pd.Series(np.random.randn(len(rng)), index=rng)
In [210]: ts
Out[210]:
2000-01-01 0.631634
2000-01-02 -1.594313
2000-01-03 -1.519937
2000-01-04 1.108752
2000-01-05 1.255853
2000-01-06 -0.024330
2000-01-07 -2.047939
2000-01-08 -0.272657
2000-01-09 -1.692615
2000-01-10 1.423830
...
2000-03-31 -0.007852
2000-04-01 -1.638806
2000-04-02 1.401227
2000-04-03 1.758539
2000-04-04 0.628932
2000-04-05 -0.423776
2000-04-06 0.789740
2000-04-07 0.937568
2000-04-08 -2.253294
2000-04-09 -1.772919
Freq: D, Length: 100, dtype: float64
In [211]: ts.resample('M').mean()
Out[211]:
2000-01-31 -0.165893
2000-02-29 0.078606
2000-03-31 0.223811
2000-04-30 -0.063643
Freq: M, dtype: float64
In [212]: ts.resample('M', kind='period').mean()
Out[212]:
2000-01 -0.165893
2000-02 0.078606
2000-03 0.223811
2000-04 -0.063643
Freq: M, dtype: float64
resample是一個靈活高效的方法,可用于處理非常大的時間序列,

加油!
感謝!
努力!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/317786.html
標籤:AI
上一篇:Python將彩色圖轉換為灰度圖
