与概率分析有关的图表包括各种分布的概率密度函数曲线图、累加分布函数曲线图、各种分布的检验图等。本节主要介绍QQ图和PP图的绘制。[大谦Excel,dqexcel点com]
QQ图
QQ图用变量数据的分位数与所指定分布的分位数之间的关系曲线来检验一元数据是否服从指定的分布。也可以用两个一元数据的分位数之间的关系曲线来检验两个样本是否来自同一分布。如果图中的数据点在对角线附近呈现直线关系,认为一元数据服从指定分布,
图5-24 QQ图
绘制QQ图的核心代码如下所示。完整代码见:Samples->ch08 统计图表->22 QQ图->py.py。代码的重点在于经验分位数和理论分位数的计算,它们的计算结果用于绘制散点图。
root=os.getcwd() #获取当前工作路径
app=xw.App(visible=True,add_book=False) #创建Excel应用
wb=app.books.open(root+r'/data.xlsx',read_only=False) #打开数据文件返回工作簿对象
sht=wb.sheets('Sheet1') #获取指定工作表对象
data=sht.range('B2:B21').value
sorted_data=sort_array(data,20)
shp=sht.api.Shapes.AddChart2() #创建空白图表
shp.Left=20
cht=shp.Chart #获取图表
cht.SetSourceData(Source=sht.api.Range('B2:B21'))
cht.ChartType=xw.constants.ChartType.xlXYScatter #图表类型为散点图
ax1=cht.Axes(1) #获取横轴
ax2=cht.Axes(2) #获取纵轴
ax1.MinimumScale=sorted_data[0] #横轴和纵轴的取值范围
ax1.MaximumScale=sorted_data[19]
ax2.MinimumScale=sorted_data[0]
ax2.MaximumScale=sorted_data[19]
ax1.CrossesAt=sorted_data[0] #坐标轴的交点
ax2.CrossesAt=sorted_data[0]
set_style(cht) #设置样式
tq=[0 for _ in range(20)]
eq=[0 for _ in range(20)]
#计算理论值
tq=tquantile(app,sorted_data)
#计算经验值
eq=equantile(sorted_data)
#创建 PP 图
cht.SeriesCollection().NewSeries() #新建序列
cht.SeriesCollection(1).XValues=tq
cht.SeriesCollection(1).Values=eq
cht.Axes(1,1).HasTitle=True
cht.Axes(1,1).AxisTitle.Text='Theoretical Quantiles'
cht.Axes(2,1).HasTitle=True
cht.Axes(2,1).AxisTitle.Text='Empirical Quantiles'
#绘对角线
bx=shape_x(cht,sorted_data[0])
by=shape_y(cht,sorted_data[0])
ex=shape_x(cht,sorted_data[19])
ey=shape_y(cht,sorted_data[19])
shp2=cht.Shapes.AddLine(bx,by,ex,ey)
shp2.Line.DashStyle=1
shp2.Line.ForeColor.RGB=xw.utils.rgb_to_int((0,0,0))
shp2.Line.Weight=1
代码中sort_array函数对给定数据进行排序,使用冒泡法进行排序。排序后的数据即是经验分位数。
def sort_array(data,n):
#使用冒泡排序对数据进行排序
for i in range(n):
for j in range(i,n):
if data[i]>data[j]:
temp=data[i]
data[i]=data[j]
data[j]=temp
return data
用tquantile函数计算理论分位数。这里使用了工作表函数Norm_S_Inv计算分位数,假设理论分布为标准正态分布。
def tquantile(app,sorted_data):
#计算理论分位数(使用标准正态分布的分位数作为示例)
length=len(sorted_data)
q=[0 for _ in range(length)]
for i in range(length):
q[i]=app.api.WorksheetFunction.Norm_S_Inv((i+1-0.5)/length)
return q
用equantile函数计算经验分位数。对于 QQ 图,经验分位数就是已排序的数据本身。
def equantile(sorted_data):
#计算经验分位数
#对于 QQ 图,经验分位数就是已排序的数据本身
return sorted_data
运行代码生成类似图5-24的QQ图。图中用经验分位数和理论分位数绘制散点,绘制绘图区左下角到右上角的连线。数据点在直线附近分布,所以认为数据服从正态分布。
PP图
PP图用变量数据的经验累积概率与所指定分布的理论累积概率之间的关系曲线来检验一元数据是否服从指定的分布。也可以用两个一元数据的分位数之间的关系曲线来检验两个样本是否来自同一分布。如果图中的数据点在对角线附近呈现直线关系,认为一元数据服从指定分布,或两变量数据取自相同分布。
图5-25 PP图
绘制PP图的核心代码如下所示。完整代码见:Samples->ch08 统计图表->23 PP图->py.py。代码的重点在于经验累积概率和理论累积概率的计算,它们的计算结果用于绘制散点图。
root=os.getcwd() #获取当前工作路径
app=xw.App(visible=True,add_book=False) #创建Excel应用
wb=app.books.open(root+r'/data.xlsx',read_only=False) #打开数据文件返回工作簿对象
sht=wb.sheets('Sheet1') #获取指定工作表对象
data=sht.range('B2:B21').value #获取数据
sorted_data=sort_array(data,20) #排序
shp=sht.api.Shapes.AddChart2() #创建空白图表
shp.Left=20
cht=shp.Chart #获取图表
cht.SetSourceData(Source=sht.api.Range('B2:B21'))
cht.ChartType=xw.constants.ChartType.xlXYScatter #图表类型为散点图
ax1=cht.Axes(1) #获取横轴
ax2=cht.Axes(2) #获取纵轴
ax1.MinimumScale=0 #横轴最小值
ax1.MaximumScale=1
ax2.MinimumScale=0 #纵轴最小值
ax2.MaximumScale=1
ax1.CrossesAt=0
ax2.CrossesAt=0
set_style(cht) #设置样式
tp=[0 for _ in range(20)]
ep=[0 for _ in range(20)]
#计算理论值
tp=tprob(app,sorted_data)
#计算经验值
ep=eprob(sorted_data)
#创建 PP 图
cht.SeriesCollection().NewSeries() #新建序列
cht.SeriesCollection(1).XValues=tp
cht.SeriesCollection(1).Values=ep
cht.Axes(1,1).HasTitle=True
cht.Axes(1,1).AxisTitle.Text='Theoretical Cumulative Probabilities'
cht.Axes(2,1).HasTitle=True
cht.Axes(2,1).AxisTitle.Text='Empirical Cumulative Probabilities'
#绘对角线
bx=shape_x(cht,0)
by=shape_y(cht,0)
ex=shape_x(cht,1)
ey=shape_y(cht,1)
shp2=cht.Shapes.AddLine(bx,by,ex,ey)
shp2.Line.DashStyle=1
shp2.Line.ForeColor.RGB=xw.utils.rgb_to_int((0,0,0))
shp2.Line.Weight=1
sort_array函数对给定数据进行排序,使用冒泡法进行排序。
用tprob函数计算理论累积概率。这里使用了工作表函数Norm_S_Dist计算理论累积概率,假设理论分布为标准正态分布。
def tprob(app,sorted_data):
#计算理论累积概率(假设使用标准正态分布的累积概率)
length=len(sorted_data)
tp=[0 for _ in range(length)]
for i in range(length):
tp[i]=app.api.WorksheetFunction.Norm_S_Dist(sorted_data[i],True)
return tp
用eprob函数计算经验累积概率。
def eprob(sorted_data):
#计算经验累积概率
#对于 QQ 图,经验分位数就是已排序的数据本身
length=len(sorted_data)
ep=[0 for _ in range(length)]
for i in range(length):
ep[i]=(i+1-0.5)/length
return ep
运行代码生成类似图5-25的PP图。图中用经验累积概率和理论累积概率绘制散点,绘制绘图区左下角到右上角的连线。数据点在直线附近分布,所以认为数据服从正态分布。