第四章:Python科学计算、数据分析、图表可视化库--Scipy
04-Python科学计算、数据分析、图表可视化库
1 Scipy入门
1.1 Scipy简介
Scipy是世界上著名的Python开源科学计算库,建立在Numpy之上。在NumPy库的基础上增加了众多的数学、科学以及工程计算中常用的库函数。例如线性代数、常微分方程数值求解、信号处理、图像处理、稀疏矩阵等等。
Scipy 官网
1.2 Scipy安装方法1:通过Python安装:pip install scipy
方法2:通过anoconda安装:conda install scipy
1.3 Scipy读写.mat文件
fromscipyimportio
io.savemat("a.mat",{"array":a})#将多维数组a保存为a.mat文件
b=io.loadmat("a.mat")#读取a.mat文件
print(b["array"])#通过字典的key值读取文件中的矩阵
2 Scipy进阶--利用Scipy实现统计功能from scipy import stats #包内提供了scipy统计相关的功能
2.1 产生连续性分布的随机函数rvs()函数,用于生成随机数
fromscipyimportstats
x=stats.norm.rvs(size=20)# 生成20个符合正态分布的随机数
print("符合正态分布的随机数:\n",x)
>>符合正态分布的随机数:
[-0.44988658-0.833431080.27943026-2.457807-0.6018228-0.36107496
-0.89004694-1.015674650.600883161.842060870.057365170.98768884
1.276853281.14725471-0.61182348-0.31744858-1.35432440.18191441
-0.30926403-0.45855603]
z=stats.beta.rvs(size=20,a=3,b=4)# 生成20个服从参数a=3,b=4的贝塔分布的随机数
print("服从参数a=3,b=4的贝塔分布的随机数:\n",z)
>>服从参数a=3,b=4的贝塔分布的随机数:
[0.200223490.228523930.724613230.357945320.410866650.4772275
0.232325190.327235740.506842840.536962360.474855390.27355876
0.540362340.457929880.347130890.762235940.086427620.67108931
0.619060870.46433408]
r=stats.poisson.rvs(0.6,loc=0,size=20)# 生成20个服从泊松分布的随机数
print("服从泊松分布的随机数:\n",r)
>>服从泊松分布的随机数:
[01011000000000023001]
2.2 计算随机数的均值和标准差fit()函数,用于计算对应方法生成随机数据的均值和标准差,返回两个值
fromscipyimportstats
x=stats.norm.rvs(size=20)# stats.norm.rvs()
mean,std=stats.norm.fit(x)# stats.norm.fit()
print("mean:",mean)# >> mean: 0.1634558886370828
print("std:",std)# >> std: 0.7626103006262862
y=stats.uniform.rvs(size=20)# stats.uniform.rvs()
mean,std=stats.uniform.fit(y)# stats.uniform.fit()
print("mean:",mean)# >> mean: 0.022533324806813096
print("std:",std)# >> std: 0.8515183320476238
2.3 计算随机数的偏度概念:偏度(skewness)——描述的是概率分布的偏斜(非对称)程度。偏度检验有两个返回值,其中第二个返回值为p_value,即观察到的数据集服从正态分布的概率,取值范围为0~1 ;
stats.skewtest(generated)
fromscipyimportstats
frommatplotlibimportpyplotasplt
normal_1=stats.norm.rvs(size=100)#生成100个符合正态分布的随机数
stat_1,p_value_1=stats.skewtest(normal_1)
print("stat_1—偏度:",statistic_1)
print("p_value_1—概率:",p_value_1)
plt.hist(normal_1)
plt.show()
>>statistic_1—偏度:-2.310562147423953
p_value_1—概率:0.020857052080527714
负偏度(偏度值<0)(均值
正偏度(偏度值>0)(均值>中位数): 2.99,p_value:服从分布的随机数的概率
2.4 计算随机数的峰度概念:峰度(kurtosis)——描述的是描述的是概率分布曲线的陡峭程度
利用stats.kurtosistest()计算峰度
fromscipyimportstats
frommatplotlibimportpyplotasplt
norm_1=stats.norm.rvs(size=500)
Kurt,p_value=stats.kurtosistest(norm_1)
print("Kurt:",Kurt)
print("p_value:",p_value)
plt.hist(norm_1)
红:实际生成数据的曲线;湖蓝:标准正态曲线
Kurt: 0.988,p_value: 0.323 -- 高峡峰(leptokurtic)
Kurt: -1.176,p_value: 0.240 -- 低阔峰(platykurtic)
2.5 检查随机数服从正态分布的程度概念:正态性检验(normality test)— —检查数据集服从正态分布的程度。该检验同样有两个返回值,其中第二个返回值 为p_value。
利用stats. normaltest()来检验 一般情况p_value>0.05即表示服从正态分布
fromscipyimportstats
norm=stats.norm.rvs(size=200)# 生成200个符合正态分布的随机数
norm_test,p_value=stats.normaltest(norm)
print("norm_test:",norm_test)
print("p_value:",p_value)
一般认为p_value>0.05即认为其服从正态分布
2.6 计算数据所在的区段中某一百分比处的数值 及 某一值对应的百分比
# stats.scoreatpercentile (数据集,百分比)
# stats.percentileofscore(generated, 1)
fromscipyimportstats
norm=stats.norm.rvs(size=20)
percent_95_value=stats.scoreatpercentile(norm,95)
percent_1=stats.percentileofscore(norm,1)
print(percent_95_value)
>>percent_95_value:1.6802186858334522#比1.68小的数据样本点占95%
percent_1:75.0#比1小的数据样本点有75%
2.7 scipy中常用统计方法总结:
stats.mode()#众数
stats.skewtest()# 偏度函数
stats.kurtosistest()#峰度函数
Stats.scoreatpercentile()#百分比出的值
stats.normaltest()#检验正态分布
stats.percentileofscore()#值对应的百分比
2.8 Scipy中线性代数应用使用scipy.linalg模块提供标准线性代数运算(与Numpy功能一致):
1、计算行列式函数: linalg.det(arr)
2、计算矩阵的逆矩阵函数:linalg.inv(arr)
3、奇异值分解(SVD)函数: uarr,spec,vharr = linalg.svd(arr)
4、解线性方程组:linalg.solve(A,b)
from scipy import linalg与import scipy.linalg的区别:区别
相同点
不同点
from scipy import linalg
实现scipy中线性代数的应用功能
调用时:linalg.det(mat)
import scipy.linalg
实现scipy中线性代数的应用功能
调用时:scipy.linalg.det(mat)
2.9 Scipy中图像处理使用模块:import matplotlib.pyplot as plt
from scipy import misc
from scipy import ndimage
import numpy as np
importmatplotlib.pyplotasplt#显示图像
fromscipyimportmisc#创建要测试的图像
fromscipyimportndimage#操作图像
importnumpyasnp
# 创建图片,scipy内置图片:misc.ascent()
image=misc.ascent()
plt.subplot(221)#画布分割,"221"分别代表画布分为两行两列,"1"代表第一块画布
plt.title("Original Image")# 添加图片标题
plt.imshow(image)# 图片显示
plt.axis("off")# 关闭图像坐标轴的显示
# 中值滤波 :ndimage.median_filter(image, size=5)
fliter=ndimage.median_filter(image,size=20)
plt.subplot(222)
plt.title("Fliter Image")
plt.imshow(fliter)
plt.axis("off")
# 旋转90度 :ndimage.rotate(image, 90)
rotate=ndimage.rotate(image,90)
plt.subplot(223)
plt.title("Rotate Image")
plt.imshow(rotate)
plt.axis("off")
# 边缘检测 :ndimage.prewitt(image)
prewitt=ndimage.prewitt(image)
plt.subplot(224)
plt.title("Prewitt Image")
plt.imshow(prewitt)# 此处没有关闭坐标轴的显示
2.10 Scipy中声音处理使用模块:from scipy.io import wavfile
fromscipy.ioimportwavfile#操作wav格式声音的文件
frommatplotlibimportpyplotasplt#用于显示声音的属性
importnumpyasnp#对声音的数据进行重复
sample_rate,data=wavfile.read("Alarm01.wav")#读取声音速率,二进制数据保存在数组中
plt.subplot(211)#画板分割
plt.title("Original")
plt.plot(data)#显示原始音频的二进制数据的图像
repeated=np.array(list(data)*2)#将原始音频的二进制数据复制一遍,存放在数组中
plt.subplot(212)
plt.title("Repeated")
plt.plot(repeated)
wavfile.write("Alarm02.wav",sample_rate,repeated)#将原文件速率,处理后的数据写入wav文件
plt.show()#将两块画板显示
3 Tushare简介
3.1 Tushare介绍
Tushare——是一个免费、开源的python财经数据接口包。主要实现对股票等金融数据从数据采集、清洗加工 到 数据存储的过程,能够为金融分析人员提供快速、整洁、和多样的便于分的数据,为他们在 数据获取方面极大地减轻工作量,使他们更加专注于策略和模型的研究与实现上。考虑到Python pandas包在金融量化分析中体现出的优势,Tushare返回的绝大部分的数据格式都是pandas DataFrame类型,便于用pandas/NumPy/scipy/Matplotlib进行数据分析和可视化。 官方网站
3.2 Tushare安装方式一:pip install tushare (该网站为国内数据接口,避免使用conda安装)
4 项目实战:检测中国平安股票线性趋势
4.1 数据获取
4.1.1 利用财经数据接口包tushare获取股票的数据常用方法import tushare as ts
方法1:ts.get_k_data()——获取个股历史交易数据(包括均线数据), 可以通过参数设置获取日k线、周k线、月k线,以及5分钟、15分钟、 30分钟和60分钟k线数据。本接口只能获取近3年的日线数据,适合搭 配均线数据进行选股和分析
方法2:ts.get_h_data()—获取个股全部或指定时间段历史交易数据
方法3:ts.get_today_all() ——一次性获取当前交易所有股票的行情数 据(如果是节假日,即为上一交易日)
4.2 项目代码实现
importtushareasts
fromdatetimeimportdatetime,timedelta
fromscipyimportsignal#导入signal模块用于信号去线性趋势
frommatplotlibimportpyplotasplt#用于绘图
fromdatetimeimportdatetime,timedelta
today=datetime.now()#获取当前日期
delta=timedelta(days=365)#通过timedelta()函数获取365的天数差
year_ago=today-delta#获取一年前的日期
start=year_ago.strftime("%Y-%m-%d")#开始日期转字符
end=today.strftime("%Y-%m-%d")#结束日期转字符
#获取数据
ZGPA_all=ts.get_h_data("000001",start=start,end=end)#获取中国平安股票一年的数据
date=ZGPA_all.index#获取日期
close=ZGPA_all["close"]#获取收盘价
#去除趋势前
plt.plot(date,close,"o",date,close,"-")#同一个图上同一份数据用两种图标作图
plt.show()
#通过signal模块去除信号中的线性趋势
z=signal.detrend(close)
plt.plot(date,close,"o",date,close-z,"-")#不同数据两种图标作一张图
plt.show()
去除信号的线性趋势之前
去除信号的线性趋势之后
在scipy中,在从其他数据源获取数据时,如需拆分组合时,如果使用列表接收需求的数据,则需要将列表转为数组,并指定数据类型(一般为np.float64)
在numpy与scipy中操作的数据几乎都为数组。
5 项目实战:获取电影票房
5.1 需求:获取昨日排行第一的电影信息包含(电影名称、累计票房及上映天数),显示该电影自放映到昨日的所有累计票房线性趋势。提示:ts.day_boxoffice(‘日期’)方法获取单日电影票房数据
5.2 项目代码实现
importtushareasts
fromscipyimportsignal
importmatplotlib.pyplotasplt
fromdatetimeimportdatetime,timedelta
importnumpyasnp
lastDay=ts.day_boxoffice()#取上一日的数据
#分别获取上一日电影上映时间和电影名称
movieDay,movieName=lastDay.MovieDay,lastDay.MovieName
targetMovieName=None# 用于保存需要分析的电影名称
# 通过循环找到上映天数大于7天,并且排名(根据单日票房)最靠前的电影:
forday,nameinzip(movieDay,movieName):
ifint(day)>=7:
targetMovieName=name# 获得天数大于7的排名第一的电影名称
break
print(targetMovieName)# >> 查看一下电影名称:复仇者联盟3:无限战争
# 定义函数将日期转为字符串
defgetDay_str(n):
today=datetime.now()
delta=timedelta(days=n)
day=today-delta
returnday.strftime("%Y-%m-%d")
# 循环获取前十天的数据
target_office=[]#保存目标票房
dates=[]#保存日期
foriinrange(9,0,-1):
date=getDay_str(i)#日期转字符串
dates.append(date)
day_data=ts.day_boxoffice(date)# 获取指定日期的电影数据
day_filmName=day_data.MovieName# 获取电影名称
day_Boxoffice=day_data.BoxOffice# 获取电影票房
forname,boxofficeinzip(day_filmName,day_Boxoffice):
ifname==targetMovieName:#通过目标电影名称获取相应信息
target_office.append(boxoffice)
#获取的票房数据为字符串,需要转为np.float类型
target_boxoffice=np.array(target_office,dtype=np.float64)
# matplotlib图像展示
# 在matplotlib中如果需要添加中文标题,需要导入模块设置
#去线性趋势化
x=signal.detrend(target_boxoffice)
frommatplotlib.font_managerimportFontProperties
plt.figure(num=1,figsize=(10,6))#调整图片大小,figsize=(weidth,heigh)
font_set=FontProperties(fname=r"c:\windows\fonts\simsun.ttc",size=15)
title="《"+targetMovieName+"》近十天票房趋势"
plt.title(title,size=25,fontproperties=font_set)
plt.plot(dates,target_boxoffice,"o",dates,target_boxoffice,"-",dates,target_boxoffice-x,"-")
plt.show()