Numpy簡介
Numpy是高性能科學計算和數據分析的基礎包。它是pandas等其他各種工具的基礎。
Numpy的主要功能:
- ndarray,一個多維數組結構,高效且節省空間
- 無需循環對數組數據進行快速運算的數學函數
- 線性代數、隨機數生成和博立葉變換功能
創建ndarray:np.array(array_list)
數組與列表的區別:
- 數組對象內的元素類型必須相同
- 數組大小不可修改
常用屬性
- T 數組的轉置
- size 數組元素的個數
- ndim 數組的維數
- shape 數組的維度大小(元祖形式)
- dtype 數組元素的數據類型
創建array
np.zeros(10) # 10個 0.的數組
np.ones(10) # 10個的1.的數組
a = np.empty(100) # 內存中存的值
np.arange(100) # 快速創建100的數組
np.arange(15).reshape(3, 5) # 創建二維數組
np.arange(2, 10, 0.3)
np.linspace(0, 50, 100) # 0 ~ 50 平分成100份
np.eye(10) # 線性代數
ndarray 批量運算
數組和標量之間的運算
a+1 1*3 1//a a**0.5 a>5
同樣大小數組之間的運算
a+b a/b a**b a%b a==b
索引
-
一位數組索引
a[5]
-
多維數組索引
- 列表式寫法
a[2][1]
- 新式寫法
a[2, 1]
- 列表式寫法
切片
- 一位數組:
a[5:8]
a[4:]
a[2:10]
- 多維數組:
a[1:2, 3:4]
a[:, 3:5]
a[:,1]
- np數組的切片與列表切片的不同:數組切片時並不會自動復制(而是創建一個視圖),在切片數組上的修改會影響原數組
copy()
方法可以創建數組的深拷貝
ndarray布爾型索引
問題:給一個數組,選出數組中所有大於5的數
答案:a[a>5]
原理
- 數組與標量的運算:a>5會對a中的每一個元素進行判斷,返回一個布爾數組
- 布爾型索引:將同樣大小的布爾數組傳進索引,會返回一個由所有
True
對應位置的元素的數組
例子:
# 1,給一個數組,選出數組中所有大於5的數
a = np.array([random.randint(1, 10) for _ in range(20)])
a[a>5] # array([8, 6, 6, 7, 7, 6, 6])
# 2,給一個數組,選出數組中所有大於5的偶數
a = np.array([random.randint(1, 10) for _ in range(20)])
a[(a>5) & (a%2==0)]
# 3,給一個數組,選出數組中所有大於5的數和偶數
a = np.array([random.randint(1, 10) for _ in range(20)])
a[(a>5) | (a%2==0)]
ndarray花式索引
根據索引位置給出值
a = np.arange(20)
a[[1,4,5,6]] # array([1, 4, 5, 6])
a = np.arange(20).reshape(4,5) # array([[ 0, 1, 2, 3, 4],
# [ 5, 6, 7, 8, 9],
# [10, 11, 12, 13, 14],
# [15, 16, 17, 18, 19]])
a[0, 2:5] # array([7, 8, 9])
a[0, a[0]>2]
a[[1, 3], [1, 3]] # 注意2個花式索引的取法,解析有點不一樣,獲取到的值是:array([ 6, 18])
# 如果就是想取6 8 16 18 可以使用下滿的方法
a[[1, 3],:][:,[1,3]] # : 表示全切
Numpy 通用函數
通用函數:能同時對數組中所有元素進行運算的函數
補充知識:
int # 向零取整
round # 向零外取整,round到兩邊距離相等時取偶數值
math.floor # 向小取整(向左取整)(地板)
math.ceil # 向大取整(向右取整)(天花)
常見通用函數:
一元函數: 對一維數組處理
np.abs(a) # 絕對值
np.sqrt(a) # 開方
np.exp(a)
np.log(a)
np.ceil(a) # 向大取整(向右取整)(天花)
np.floor(a) # 向小取整(向左取整)(地板)
np.rint(a) # 等價於 round
np.round(a) # 向零外取整,round到兩邊距離相等時取偶數值
np.trunc(a) # 向零取整
np.modf(a) # 將小數和整數拆開
np.isnan(a) # 過濾nan
np.isinf(a) # 過濾inf
np.cos(a)
np.sin(a)
np.tan(a)
例子
a = np.arange(-5.5,5)
np.abs(a)
x, y = np.modf(a) # 將小數和整數拆開,x是小數,y是整數
# numpy過濾nan
a = np.arange(0,5)
b = a/a # array([nan, 1., 1., 1., 1.])
b[~np.isnan(b)] # ~ 是取反
# numpy過濾inf
a=np.array([3,4,5,6])
b=np.array([2,0,3,0])
c = a/b
c[c!=np.inf] # 過濾inf
c[~np.isinf(c)] # 過濾inf
二元函數: 對二維數組處理
np.add(a,b) # a數組 + b數組
np.subtract(a,b) # a-b 一般不用調函數,直接對數組相加就好
np.multiply(a,b)
np.divide(a,b)
np.power(a,b)
np.mod(a,b)
np.maximum(a,b) # 兩個數組中的最大
np.minimum(a,b) # 兩個數組中的最小
Numpy 數學和統計方法
sum # 求和
mean # 求平均值
std # 求標准差
var # 求方差
min # 求最小值
max # 求最大值
argmin # 求最小值索引
argmax # 求最大值索引
# 求方差
1 2 3 4 5
mean:3
((1-3)**2+(2-3)**2+(3-3)**2+(4-3)**2+(5-3)**2)/5
# 方差表示你這組數據的離散程度
標准差 = sqrt(方差)
# 差不多60%的數據分布在這區間
a.mean()+a.std()
a.mean()-a.std()
# 差不多80%的數據分布在這區間
a.mean()+2*a.std()
a.mean()-2*a.std()
Numpy 隨機數生成
隨機數函數在np.random
子包內
np.random.rand 給定形狀產生隨機數組(0 ~ 1之間)
np.random.randint 給定**長度**產生隨機整數
np.random.choice 給定形狀產生隨機選擇
np.random.shuffle 與random.shuffle相同
np.random.uniform 給定形狀產生隨機數組
例子
np.random.randint(0, 10, 10) # 生成一個長度10的隨機數組
np.random.rand(5)
np.random.choice([1,2,3,4,5], (2,3))
np.random.uniform(2,5, (3,4))
補充 - 浮點數特殊值
nan (Not a Number)
: 不等於任何浮點數(nan != nan)inf(infinity)
:比任何浮點數都大- Numpy中創建特殊值:
np.nan
np.inf
- 在數據分析中,
nan
常被用作表示數據缺失值
Pandas 數據分析
pandas簡介
pandas是一個強大的Python數據分析的工具包,是基於NumPy構建的。
pandas的主要功能:
- 具備對其功能的數據結構DataFrame、Series
- 集成時間序列功能
- 提供豐富的數學運算和操作
- 靈活處理缺失數據
安裝方法:pip install pandas
引用方法:import pandas as pd
Series 一維數組對象
Series是一種類似於一維數組的對象,由一組數據和一組與之相關相關的數據標簽(索引)組成。
創建方式:
pd.Series([4, 5, -5, 3])
pd.Series([4, 5, -5, 3], index=['a', 'b', 'c', 'd'])
pd.Series({'a': 1, 'b': 2, 'c': 3})
pd.Series(0, index=['a', 'b', 'c'])
合並兩個Series
sr = sr1.append(sr2).sort_index() # 方式二 (0,死叉) (1,金叉)
獲取值數組和索引數組:values
屬性和index
屬性
Series比較像列表(數組)和字典的結合體
Series 使用特性
Series支持array的(下標)特性:
- 從
ndarray
創建Series:Series(arr)
- 與標量運算:
sr * 2
- 兩個Series運算:
sr1+sr2
- 索引:
sr[0]
[sr[[1,2,4]]]
- 切片:
sr[0:2]
- 通用函數:
np.abs(sr)
- 布爾值過濾:
sr[sr>0]
Series支持字典的特性(標簽)
- 從字典創建Series:
Series(dic)
- in運算:
'a' in sr
- 鍵索引:
sr['a']
sr[['a', 'b', 'd']]
sr.index
sr.values
sr.index[0]
sr[[1, 3]]
sr[['a', 'd']]
sr['a': 's'] # 通過標簽切片,前包后也包
Series 整數索引
pandas Series對象的整數索引往往會使新手抓狂。
例如:
sr = pd.Series(np.arange(4))
sr[-1] # 會報錯
如果索引是整數類型,則根據整數進行下標獲取值時總是面向標簽的。
解決辦法:loc
屬性(將索引解釋為標簽)和iloc
屬性(將索引解釋為下標)
sr2.loc[10] # 根據標簽索引
sr2.iloc[10] # 根據下標索引
sr2.iloc[-1]
sr2.iloc[3:6]
sr2.iloc[[2, 3, 7]]
Series 數據對齊
兩個series數組對象,將會根據索引對齊后再相加
sr1 = pd.Series([11,23,34], index=['c','a','d'])
sr2 = pd.Series([11,20,10], index=['d','c','a'])
sr1+sr2 # 將會按照index對齊之后進行相加
sr1 = pd.Series([11,23,34], index=['c','a','d'])
sr2 = pd.Series([11,20,10,21], index=['d','c','a','b'])
sr1+sr2 # 出現缺省值,b 將會用 NaN 代替
sr1 = pd.Series([11,23,34], index=['b','a','d'])
sr2 = pd.Series([11,20,10], index=['d','c','a'])
sr1+sr2 # b NaN c NaN
sr1 = pd.Series([11,23,34], index=['b','a','d'])
sr2 = pd.Series([11,20,10], index=['d','c','a'])
# 如何使結果在索引`b`處的值為11,在索引`c`處的值為20
# 靈活的算術方法:add sub div mul
sr1.add(sr2, fill_value=0) # sr1 + sr2 , 有NaN就用0代替
Series 缺失值的處理
sr.isnull() # NaN 返回 True
sr.notnull() # not NaN 返回 True
# 丟掉
sr = sr[sr.notnull()]
sr = sr.dropna()
# 填充成其他值
sr = sr.fillna(0) # 使用0填充
sr = sr.fillna(sr.mean()) # 使用平均值填充
DataFrame的創建方式
dataframe的列得是同一個類型
DataFrame是一個表格型的數據結構,含有一組有序的列。DataFrame可以被看作是由Series組成的字典,並且共用一個索引。
創建方式
# 方式一
pd.DataFrame({'one': [1,2,3], 'two': [4,5,6]})
pd.DataFrame({'one': [1,2,3], 'two': [4,5,6]}, index=['a','b','c'])
# 方式二
pd.DataFrame({'one':pd.Series([1,2,3],index=['a','b','c']), 'two':pd.Series([1,2,3,4], index=['b','a','c','d'])})
csv文件讀取與寫入
df.to_csv('test2.csv')
pd.read_csv('test2.csv')
DataFrame 常用屬性
index 行索引
T 轉置
columns 獲取列索引
values 獲取值數組 (二維數組)
describe() 獲取快速統計
DataFrame 索引和切片
DataFrame是一個二維數據類型,所以有行索引和列索引。
DataFrame同樣可以銅鼓標簽和位置兩種方法進行索引和切片
loc
屬性和iloc
屬性
- 使用方法:逗號隔開,前面是行索引,后面是列索引
- 行/列索引部分可以是常規索引、切片、布爾值索引、花式索引任意搭配
loc
會將行解釋為索引標簽,iloc
會將行解釋為其索引下標
df['one']['a'] # one是列索引,a是行索引
df.loc['a', 'one'] # 推薦這種,a 是 行索引,one是列索引
df.loc['a',:] # 切片 a 這一行數據
df.loc[['a','c'],:]
df.loc[['a','c'],'two'] # 任意搭配
DataFrame 數據對齊與缺省數據
DataFrame對象在運算時,同樣會進行數據對齊,其行索引和列索引分別對齊。
DataFrame處理缺省數據的相關方法:
dropna(axis=0,how='any',...) # axis=0按行刪;axis=1按列刪。how='any' 出現一個就刪,how='all'都出現才刪。
fillna() # 填充
isnull()
notnull()
df.dropna(how='all') # 都出現才刪除 默認是 any
df2.dropna(axis=1) # 按列刪 默認是0
Pandas 其他常用方法
mean(axis=0, skipna=False) 對列(行)求平均值
sum(axis=1) 對列(行)求平均值
sort_index(axio,...,ascending) 對列(行)索引排序
sort_values(by, axis, ascending) 按某一列(行)的值排序,注意:有nan的不參與排序 放到最后顯示
# Numpy的通用函數同樣適用於pandas
例子
f.sort_values(by='two') # 按two列排序
df.sort_values(by='two', ascending=False) # 按two降序排序
df.sort_values(by=1, ascending=False, axis=1) # 按1這一行降序排序
df.sort_index() # 按行索引排序
df.sort_index(ascending=False) # 按行索引降序排序
df.sort_index(ascending=False, axis=1) # 按列索引降序排序
Pandas 時間對象
時間序列類型:
- 時間戳:特定時刻
- 固定日期:如2017年7月
- 時間間隔:起始時間-結束時間
Python標准庫處理時間對象:datetime
靈活處理時間對象: dateutil
dateutil.parser.parse()
成組處理事件對象:pandas
pd.to_datetime()
datetime.datetime.strptime('2010-08-21', '%Y-%m-%d')
import dateutil
dateutil.parser.parse('2001-01-01')
dateutil.parser.parse('200101/01')
dateutil.parser.parse('2001/01/01')
dateutil.parser.parse('01/01/2020')
pd.to_datetime(['2019-01-01','2010/Feb/02'])
Pandas 時間對象處理
產生時間對象數組 date_range
start 開始時間
end 結束時間
period 時間長度
freq 時間頻率,默認為'D', 可選H(our), W(eek), B(usiness),S(emi-)M(onth),(min)T(es), S(econd), A(year), ...
pd.date_range('2010-01-01','2010-5-1')
pd.date_range('2010-01-01',periods=60)
pd.date_range?
pd.date_range('2010-01-01',periods=60,freq='H')
pd.date_range('2010-01-01',periods=60,freq='W')
pd.date_range('2010-01-01',periods=60,freq='W-MON')
pf = pd.date_range('2010-01-01',periods=60,freq='B')
pd.date_range('2010-01-01',periods=60,freq='1h20min')
df[0].to_pydatetime() # 轉換成Python的datetime類型
將索引轉換為時間列
df['date'] = pd.to_datetime(df['date'])
df.set_index("date", inplace=True)
# df.set_index('date',drop=True)
Pandas 時間序列
時間序列就是以時間對象為索引的Series或DataFrame
datetime對象作為索引時是存儲在DatetimeIndex對象中的
時間序列特殊功能:
- 傳入“年”或“年月”作為切片方式
- 傳入日期范圍作為切片方式
- 豐富的函數支持:resample(), truncate() ....
sr = pd.Series(np.arange(1000), index=pd.date_range('2017-1-1', periods=1000))
sr['2017-3']
sr['2017-4']
sr['2017']
sr['2017':'2018-3']
sr['2017-12-24':'2018-2-1']
sr.resample('W').sum() # 按周求和
sr.resample('m').sum()
sr.resample('m').mean()
sr.resample('M').first() # 每個月第一天數據
sr.truncate(before='2018-2-3') # 切掉掉前面的,因為有時間切片了,所以不推薦這個方法
sr.truncate(after='2018-2-3')
Pandas 文件處理
數據文件常用格式:csv
(以某間隔符分割字符)
pandas讀取文件:從文件名、URL、文件對象中加載數據
read_csv
默認分隔符為逗號read_table
默認分隔符為制表符
read_csv
read_table
函數主要參數
sep 指定分隔符,可用正則表達式,如'\s+', 不指定則默認是 `,`
header=None 指定文件無列名
names 指定列名
index_col 指定某列作為索引
skip_row 指定跳過某些行
na_values 指定某些字符串表示缺失值(將某些奇怪字符串解析成NaN)
parse_dates 指定某些列是否被解析為日期,類型為布爾型或列表
例子
# 常用
df = pd.read_csv('zn2006SHFE2020.csv', index_col='datetime', parse_dates=['datetime'])[['open','high','low','close']]
pd.read_csv('zn2006.csv')
pd.read_csv('zn2006.csv', index_col=0) # 指定第0列為索引
pd.read_csv('zn2006.csv', index_col='datetime') # 指定`datetime`列為索引
pd.read_csv('zn2006.csv', index_col='datetime', parse_dates=True)
pd.read_csv('zn2006.csv', index_col='datetime', parse_dates=['datetime'])
pd.read_csv('zn2006.csv', header=None)
pd.read_csv('zn2006.csv', header=None, names=list('qwertyuiopasdfg'))
pd.read_csv('zn2006.csv', header=None, skiprows=[2,3,4])
pd.read_csv('zn2006.csv', na_values=['None']) # 將None替換為NaN
寫入到CSV文件:to_csv
函數
寫入文件函數的主要參數:
sep 指定文件分隔符
na_rep 指定缺失值轉換的字符串,默認為空字符串
header=False 不輸出列名一行
index=False 不輸出行索引一行
cols 指定輸出的列,傳入列表
df.to_csv('test.csv', header=False, index=False, na_rep='null')
df.to_csv('test.csv', header=False, index=False, na_rep='null',columns=['open','high','low','close'])
df.to_html('test.html')
pd.read_excel('test.xlsx')
pandas支持的其他文件類型
- json
- xml
- html
- 數據庫
- pickle
- excel
補充
rolling函數
可以取前10的窗口
df['pre_high'] = df['high'].rolling(10).max()
shift
平移函數
通過shift函數里面的值來控制向前還是向后偏移, 缺少的值會填充NaN,groupby函數里的參數控制基於什么字段進行shift.
注意:-1
是向前前移
df16['pre_close'] = df16['close'].shift(1) # 向后偏移
temp['value_shift'] = temp.groupby('id')['value'].shift(1);temp
Out[180]:
id value value_shift
0 1 1 NaN
1 1 2 1.0
2 1 3 2.0
3 2 4 NaN
4 2 5 4.0
5 3 6 NaN
temp['value_shift_1'] = temp.groupby('id')['value'].shift(-1);temp
Out[181]:
id value value_shift value_shift_1
0 1 1 NaN 2.0
1 1 2 1.0 3.0
2 1 3 2.0 NaN
3 2 4 NaN 5.0
4 2 5 4.0 NaN
5 3 6 NaN NaN
通過shift
函數里面的值來控制向前還是向后偏移, 缺少的值會填充NaN
.
groupby
函數里的參數控制基於什么字段進行shift
.
補充函數
series.describe() # 總結數據分布情況
np.sign(<series/array>) # sign()是Python的Numpy中的取數字符號(數字前的正負號)的函數。(大於0,返回1) ;(等於0,返回0);(小於0,返回-1)
Series.value_counts() # 統計值的出現次數
series.cumsum() # 累加之前的數據
series.cumprod() # 累乘之前的數據
series.pct_change() # 表示當前元素與先前元素的相差百分比,當然指定periods=n,表示當前元素與先前第n 個元素的相差百分比。可以用來算當天較上一天的return(收益)