Python数据分析常见库介绍之Scipy
Scipy是一个高级的科学计算库,它和Numpy联系很密切,Scipy一般都是操控Numpy数组来进行科学计算,Scipy让Python成为了半个MATLAB。Scipy包含的功能有最优化、线性代数、积分、插值、拟合、特殊函数、快速傅里叶变换、信号处理和图像处理、常微分方程求解和其他科学与工程中常用的计算,而这些功能都是我们在之后进行数据分析需要的。下面是一些常用的Scipy的子模块。
模块名 | 功能 |
scipy.cluster | 聚类 |
scipy.constants | 数学常量 |
scipy.fftpack | 快速傅里叶变换 |
scipy.integrate | 积分 |
scipy.interpolate | 插值 |
scipy.io | 数据输入输出 |
scipy.linalg | 线性代数 |
scipy.ndimage | N维图像 |
scipy.odr | 正交距离回归 |
scipy.optimize | 优化算法 |
scipy.signal | 信号处理 |
scipy.sparse | 稀疏矩阵 |
scipy.spatial | 空间数据结构和算法 |
scipy.special | 特殊数学函数 |
scipy.stats | 统计函数 |
Scipy是依赖于numpy的,所以在安装Scipy前需要先安装好Numpy。安装Scipy的方法和安装Numpy的方法是一样的,这里不再提及。由于Scipy非常的完备且复杂,在日常的数据分析中,并不是每一个都会用上,本文就简单介绍几个常用的并且比较有趣的子模块。
输入与输出(scipy.io)
scipy.io模块提供了多种功能来解决不同格式的文件输入和输出,包括Matlab,Wave,Arff,Matrix Market等等,最常见的是Matlab格式的。
import scipy.io as sio
#保存一个Matlab文件,后缀名是mat
vect = np.arange(20)
sio.savemat('sample.mat', {'vect':vect})
#打开一个Matlab文件
mat_file_content = sio.loadmat('sample.mat')
print (mat_file_content)loadmat()是打开一个Matlab文件,savemat()是保存一个Matlab文件,通过whosmat()可以列出Matlab文件中的变量。
优化算法(scipy.optimize)
Scipy的optimize模块提供了许多数值优化算法
非线性方程组求解(fsolve())
#求解非线性方程组2x1-x2^2=1,x1^2-x2=2
from scipy.optimize import fsolve #导入求解方程组的函数
def f(x): #定义要求解的方程组
x1 = x[0]
x2 = x[1]
return [2*x1 - x2**2 - 1, x1**2 - x2 -2]
result = fsolve(f, [1,1]) #输入初值[1, 1]并求解
print(result) #输出结果,为array([ 1.91963957, 1.68501606])最小二乘拟合(leastsq())
from scipy.optimize import leastsq
x = np.array([8.19,2.72,6.39,8.71,4.7,2.66,3.78])
y = np.array([7.01,2.78,6.47,6.71,4.1,4.23,4.05])
def residual(p):
k,b = p
return y-(k*x+b)
r = leastsq(residual,[1,0])
k,b = r[0]
print (k,b) #输出结果为0.6134953491930442 1.794092543259387除了上述的方程组求解和最小二乘拟合,Optimize还提供了诸如正弦波或者余弦波的曲线拟合(curve_fit()),全局最小值(basinhopping())等等函数,基本能够满足我们进行优化求解的需求。
统计函数(scipy.stats)
stats模块提供了大约80种连续随机变量和10多种离散分布变量,连续的和离散的随机变量都被包含在内。所有的连续随机变量都是rv_continuous的派生类的对象,而所有的离散随机变量都是rv_discrete的派生类的对象。此处以最常见的正态分布为例了解一下stats的基本用法。
生成服从指定分布的随机变量
norm.rvs通过loc和scale参数可以指定随机变量的偏移和缩放参数,这里对应的是正态分布的期望和标准差,标准差是方差的算术平方根。size得到随机数数组的形状参数。(也可以使用np.random.normal(loc=0.0,scale=1.0,size=None))
from scipy import stats
#生成10个期望是0,标准差是1的正态分布随机变量
stats.norm.rvs(loc = 0,scale = 1,size =10)
#生成3行两列期望是2,标准差差是10的正态分布随机变量
stats.norm.rvs(loc = 2,scale = 10,size=(3,2))概率密度函数和累积分布函数
stats.norm.pdf用以求正态分布概率密度函数,stats.norm.cd用以正态分布累计概率密度函数。
sample = np.random.randn(10)
#pdf(x, loc, scale),输入x,返回概率密度函数
stats.norm.pdf(sample,loc = 0,scale = 1)
#cdf(x, loc, scale),输入x,返回概率,既密度函数的面积
stats.norm.cdf(sample,loc=3,scale=1) 统计检验
stats子模块也包括了诸如kstest 和normaltest等样本测试函数,用来检测样本是否服从某种分布。
sample = np.random.randn(100)
#用normaltest检验原假设
out = stats.normaltest(sample)
print (out) #输出结果为NormaltestResult(statistic=0.5744371686350016, pvalue=0.7503476966711264)
# kstest 是检验拟合度的Kolmogorov-Smirnov检验,这里针对正态分布进行检验
# statistic的值是KS统计量的值,越接近0越好
out = stats.kstest(sample, 'norm')
print (out) #输出结果为KstestResult(statistic=0.10850663258563678, pvalue=0.1763924285692815)
# 类似地可以针对其他分布进行检验,例如Wald分布
out = stats.kstest(sample, 'wald')
print (out) #输出结果为KstestResult(statistic=0.5297870596312018, pvalue=0.0)除此之外,stats模块中还提供了一些描述函数,如下表,这里就不详细讲了,可以通过官网文档进行相关学习。
| 函数 | 描述 |
|---|---|
| describe() | 计算传递数组的几个描述性统计信息 |
| gmean() | 计算沿指定轴的几何平均值 |
| hmean() | 计算沿指定轴的谐波平均值 |
| kurtosis() | 计算峰度 |
| mode() | 返回模态值 |
| skew() | 测试数据的偏斜度 |
| f_oneway() | 执行单向方差分析 |
| iqr() | 计算沿指定轴的数据的四分位数范围 |
| zscore() | 计算样本中每个值相对于样本均值和标准偏差的z值 |
| sem() | 计算输入数组中值的标准误差(或测量标准误差) |
聚类
scipy.cluster是一个做聚类的子模块,它主要包含两类聚类方法,一是矢量聚类(scipy.cluster.vq),支持vector quantization 和 k-means 聚类方法;二是层次聚类(scipy.cluster.hierarchy):支持hierarchical clustering 和 agglomerative clustering(凝聚聚类) 。这里主要展示一下最常用的层次聚类和k-means聚类。
层次聚类(scipy.cluster.hierarchy)
import scipy
import scipy.cluster.hierarchy as sch
#生成待聚类的数据点,这里生成了20个点,每个点4维:
points=scipy.randn(20,4)
#生成点与点之间的距离矩阵,这里用的欧氏距离:
dis = sch.distance.pdist(points,'euclidean')
#进行层次聚类:
Z=sch.linkage(dis,method='average')
#将层级聚类结果以树状图表示出来
P=sch.dendrogram(Z)
#根据linkage matrix Z得到聚类结果:
cluster= sch.fcluster(Z, t=1)
print (cluster) #输出结果为[2 6 3 1 5 5 2 3 3 6 3 2 4 4 1 4 3 4 5 5]树状图如下:
k-means 聚类
from scipy.cluster.vq import vq,kmeans,whiten
#将原始数据做归一化处理
data=whiten(scipy.randn(20,4))
#使用kmeans函数进行聚类,输入第一维为数据,第二维为聚类个数k.
#k-means最后输出的结果其实是两维的,第一维是聚类中心,第二维是损失distortion,我们在这里只取第一维,所以最后有个[0]
centroid=kmeans(data,max(cluster))[0]
#使用vq函数根据聚类中心对所有数据进行分类,vq的输出也是两维的,[0]表示的是所有数据的label
label=vq(data,centroid)[0]
print (label) #输出结果为[5 5 3 4 4 5 1 5 5 4 4 5 2 1 0 4 5 2 2 3]有些时候我们可能不知道最终究竟聚成多少类,一个办法是用层次聚类的结果进行初始化。当然也可以直接输入某个数值。
通过上面的一些代码演示,相信你一定对Scipy有了一定的了解。如果你遇到了什么不能解决的问题,可以自行搜索获得解答。
在下一次的推送中,我们将对Pandas库进行相关的学习。