统计图表中常常把不同类型的图表组合在一起组成一个新的图表,这个新图表兼具有组成它的每个图表的用途,可以为使用者提供绘图数据的更多的信息。比如5.3.2小节介绍的小提琴图样式2就组合了简单小提琴图和箱形图,从而让使用者对数据有更多的了解。本节介绍更多组合图,包括云雨图、误差柱状图、散点柱状图和散点箱形图等。[大谦Excel,dqexcel点com]
云雨图
云雨图是核密度估计曲线图、箱形图和抖动散点图等图表类型的组合,根据参与组合的图表类型的不同,可以有不同的样式。下面介绍3种常见样式。
云雨图样式1由核密度估计曲线图和抖动散点图组合而成,如图5-17所示。上有云,下有雨,很形象。抖动散点图直接显示了绘图数据的分布特征。
图5-17 云雨图样式1
用draw_kde函数绘制核密度估计曲线图,用draw_rnd_scatter_h函数绘制水平放置的抖动散点图。调用这两个函数绘制云雨图样式1。完整代码见:Samples->ch08 统计图表->15 云雨图->py.py。
...
DrawKDE cht, D1, lngCount(1), 1 + 0.2, 0, 0, 255, -4, 4
DrawRndScatterH cht, D1, lngCount(1), 1, 0.5
DrawKDE cht, D2, lngCount(2), 3 + 0.2, 0, 0, 255, -4, 4
DrawRndScatterH cht, D2, lngCount(1), 3, 0.5
DrawKDE cht, D3, lngCount(3), 5 + 0.2, 0, 0, 255, -4, 4
DrawRndScatterH cht, D3, lngCount(3), 5, 0.5
...
第2种样式的云雨图由核密度估计曲线图和箱形图组合而成,如图5-18所示。该样式的作用跟上面介绍的小提琴图样式2一样。
图5-18 云雨图样式2
用draw_kde函数绘制核密度估计曲线图,用draw_boxplot_h函数绘制水平放置的箱形图。调用这两个函数绘制云雨图样式2。完整代码见:Samples->ch08 统计图表->16 云雨图2->py.py。
...
DrawKDE cht, D1, lngCount(1), 1 + 0.2, 0, 0, 255, -4, 4
DrawBoxplotH cht, D1, lngCount(1), 1, 0, 0, 255, 0.1, False
DrawKDE cht, D2, lngCount(2), 3 + 0.2, 0, 0, 255, -4, 4
DrawBoxplotH cht, D2, lngCount(2), 3, 0, 0, 255, 0.1, False
DrawKDE cht, D3, lngCount(3), 5 + 0.2, 0, 0, 255, -4, 4
DrawBoxplotH cht, D3, lngCount(3), 5, 0, 0, 255, 0.1, False
...
3种样式的云雨图由核密度估计曲线图、箱形图和抖动散点图组合而成,如图5-19所示。该样式的云雨图兼具了各种图表的优点,可以直接探查原始数据的分布,也可以用统计量和概率密度了解数据的总体特征。
图5-19 云雨图样式3
用draw_kde函数绘制核密度估计曲线图,用draw_boxplot_h函数绘制水平放置的箱形图,用draw_rnd_scatter_h函数绘制水平放置的抖动散点图。调用这三个函数绘制云雨图样式3。完整代码见:Samples->ch08 统计图表->17 云雨图3->py.py。
‘省略部分代码
draw_kde(cht,d1,1+0.2,0,0,255,-4,4)
draw_rnd_scatter_h(cht,d1,count1,1-0.2,0.5)
draw_boxplot_h(app2,cht,d1,count1,1,0,0,255,0.1,False)
draw_kde(cht,d2,3+0.2,0,0,255,-4,4)
draw_rnd_scatter_h(cht,d2,count2,3-0.2,0.5)
draw_boxplot_h(app2,cht,d2,count2,3,0,0,255,0.1,False)
draw_kde(cht,d3,5+0.2,0,0,255,-4,4)
draw_rnd_scatter_h(cht,d3,count3,5-0.2,0.5)
draw_boxplot_h(app2,cht,d3,count3,5,0,0,255,0.1,False)
‘省略部分代码
误差柱状图
误差柱状图由柱状图和误差条图组合而成。柱状图一般用来表示各组数据的均值的大小,误差条图表示置信区间或标准差等。误差柱状图如图5-20所示。
图5-20 误差柱状图
用Python xlwings编程绘制误差柱状图时,笔者试图先创建柱状图,然后利用序列对象的Hasbars属性、ErrorBars属性和ErrorBar属性等添加误差条图,如下面代码所示。但操作没有成功,误差条始终加不上。
所以,最后考虑自己绘制柱状图和误差条图,如下面代码所示。完整代码见:Samples->ch08 统计图表->18 误差柱状图->py.py。
Sub Test()
Dim shp As Shape
Dim cht As Chart
Set shp = ActiveSheet.Shapes.AddChart2()
Set cht = shp.Chart
cht.ChartType = xlXYScatter
cht.Axes(1).MinimumScale = 0.3
cht.Axes(1).MaximumScale = 6.7
cht.Axes(2).MinimumScale = 0
cht.Axes(2).MaximumScale = 0.25
Dim intI As Integer
If cht.SeriesCollection.Count > 0 Then
For intI = cht.SeriesCollection.Count To 1 Step -1
cht.SeriesCollection(intI).Delete
Next
cht.HasLegend = False
End If
cht.SeriesCollection.NewSeries
Dim ax1 As Axis
Dim ax2 As Axis
Set ax1 = cht.Axes(1)
Set ax2 = cht.Axes(2)
ax1.CrossesAt = ax1.MinimumScale
ax2.CrossesAt = ax2.MinimumScale
SetStyle cht
Dim dblMn()
Dim lx As Double
Dim ly As Double
Dim ww As Double
Dim hh As Double
dblMn = Range("B2:B7")
For intI = 1 To 6
DrawBar cht, CDbl(dblMn(intI, 1)), CDbl(intI), 0, 0, 255, 0.5, False
Next
Dim dblUp()
Dim dblDn()
Dim shp2 As Shape
dblUp = Range("C2:C7")
dblDn = Range("D2:D7")
For intI = 1 To 6
bx = ShapeX(cht, CDbl(intI))
ex = ShapeX(cht, CDbl(intI))
by = ShapeY(cht, CDbl(dblMn(intI, 1)))
ey = ShapeY(cht, CDbl(dblUp(intI, 1) + dblMn(intI, 1)))
Set shp2 = cht.Shapes.AddLine(bx, by, ex, ey)
shp2.Line.ForeColor.RGB = RGB(0, 0, 0)
shp2.Line.Weight = 1
bx = ShapeX(cht, CDbl(intI))
ex = ShapeX(cht, CDbl(intI))
by = ShapeY(cht, CDbl(dblMn(intI, 1)))
ey = ShapeY(cht, CDbl(dblMn(intI, 1) - dblDn(intI, 1)))
Set shp2 = cht.Shapes.AddLine(bx, by, ex, ey)
shp2.Line.ForeColor.RGB = RGB(0, 0, 0)
shp2.Line.Weight = 1
bx = ShapeX(cht, CDbl(intI - 0.5 / 4))
ex = ShapeX(cht, CDbl(intI + 0.5 / 4))
by = ShapeY(cht, CDbl(dblUp(intI, 1) + dblMn(intI, 1)))
ey = ShapeY(cht, CDbl(dblUp(intI, 1) + dblMn(intI, 1)))
Set shp2 = cht.Shapes.AddLine(bx, by, ex, ey)
shp2.Line.ForeColor.RGB = RGB(0, 0, 0)
shp2.Line.Weight = 1
bx = ShapeX(cht, CDbl(intI - 0.5 / 4))
ex = ShapeX(cht, CDbl(intI + 0.5 / 4))
by = ShapeY(cht, CDbl(dblMn(intI, 1) - dblDn(intI, 1)))
ey = ShapeY(cht, CDbl(dblMn(intI, 1) - dblDn(intI, 1)))
Set shp2 = cht.Shapes.AddLine(bx, by, ex, ey)
shp2.Line.ForeColor.RGB = RGB(0, 0, 0)
shp2.Line.Weight = 1
Next
cht.SeriesCollection.NewSeries
Dim intN As Integer
intN = cht.SeriesCollection.Count
cht.FullSeriesCollection(intN).ChartType = xlXYScatterLinesNoMarkers
cht.FullSeriesCollection(intN).XValues = Array(0, 7)
cht.FullSeriesCollection(intN).Values = Array(0, 0)
cht.FullSeriesCollection(intN).Format.Line.ForeColor.RGB = RGB(0, 0, 0)
cht.FullSeriesCollection(intN).Format.Line.Weight = 1
End Sub
运行代码后生成图5-20所示的误差柱状图。
散点柱状图
散点柱状图在柱状图基础上叠加绘制抖动散点图,如图5-21所示。该图给出了各组数据的均值统计量和数据点本身。
图5-21 散点柱状图
用draw_bar函数绘制柱状图,用draw_rnd_scatter函数绘制抖动散点图。调用这两个函数绘制散点柱状图。完整代码见:Samples->ch08 统计图表->19 散点柱状图->py.py。
Sub Test()
Dim intI As Integer
Dim Data()
Dim dblDt1(0 To 19) As Double
Dim dblDt2(0 To 19) As Double
Dim dblDt3(0 To 19) As Double
Dim dblDt4(0 To 19) As Double
Dim dblMean(3) As Double
Data = Range("B2:E21").Value
For intI = 0 To 19
dblDt1(intI) = CDbl(Data(intI + 1, 1))
dblDt2(intI) = CDbl(Data(intI + 1, 2))
dblDt3(intI) = CDbl(Data(intI + 1, 3))
dblDt4(intI) = CDbl(Data(intI + 1, 4))
Next
dblMean(0) = Application.WorksheetFunction.Average(dblDt1)
dblMean(1) = Application.WorksheetFunction.Average(dblDt2)
dblMean(2) = Application.WorksheetFunction.Average(dblDt3)
dblMean(3) = Application.WorksheetFunction.Average(dblDt4)
Dim shp As Shape
Dim cht As Chart
Set shp = ActiveSheet.Shapes.AddChart2()
Set cht = shp.Chart
cht.ChartType = xlXYScatter
cht.Axes(1).MinimumScale = 0.5
cht.Axes(1).MaximumScale = 4.5
cht.Axes(2).MinimumScale = 0
cht.Axes(2).MaximumScale = 0.35
SetStyle cht
cht.SeriesCollection.NewSeries
Dim intN As Integer
intN = cht.SeriesCollection.Count
cht.FullSeriesCollection(intN).ChartType = xlColumnClustered
cht.FullSeriesCollection(intN).XValues = Array(1, 2, 3, 4)
cht.FullSeriesCollection(intN).Values = dblMean
cht.FullSeriesCollection(intN).Format.Fill.ForeColor.RGB = RGB(76, 200, 132)
cht.ChartGroups(1).GapWidth = 130
DrawRndScatter cht, 1, dblDt1, 20, 0.5
DrawRndScatter cht, 2, dblDt2, 20, 0.5
DrawRndScatter cht, 3, dblDt3, 20, 0.5
DrawRndScatter cht, 4, dblDt4, 20, 0.5
cht.SeriesCollection.NewSeries
intN = cht.SeriesCollection.Count
cht.FullSeriesCollection(intN).ChartType = xlXYScatterLinesNoMarkers
cht.FullSeriesCollection(intN).XValues = Array(0.5, 4.5)
cht.FullSeriesCollection(intN).Values = Array(0, 0)
cht.FullSeriesCollection(intN).Format.Line.ForeColor.RGB = RGB(0, 0, 0)
cht.FullSeriesCollection(intN).Format.Line.Weight = 1
End Sub
运行代码生成类似图9-21所示的散点柱状图。
散点箱形图
散点箱形图在箱形图基础上叠加绘制抖动散点图,如图5-22和图5-23所示。散点箱形图给出了各组数据的分位数统计量和数据点本身。
图5-23 用自定义函数绘制散点箱形图
用draw_boxplot函数绘制箱形图,用draw_rnd_scatter函数绘制抖动散点图。调用这两个函数绘制散点箱形图。完整代码见:Samples->ch08 统计图表->21 散点箱形图-自定义->py.py。
Sub Test()
Dim intI As Integer
Dim intJ As Integer
Dim D1() As Double
Dim D2() As Double
Dim D3() As Double
Dim D4() As Double
Dim D5() As Double
Dim D6() As Double
Dim intCount(1 To 6) As Integer
For intI = 1 To 6
intCount(intI) = 0
Next
Dim data()
data = Range("B2:C101").Value
For intJ = 1 To 100
If data(intJ, 2) = 1 Then
intCount(1) = intCount(1) + 1
ReDim Preserve D1(intCount(1))
D1(intCount(1)) = data(intJ, 1)
ElseIf data(intJ, 2) = 2 Then
intCount(2) = intCount(2) + 1
ReDim Preserve D2(intCount(2))
D2(intCount(2)) = data(intJ, 1)
ElseIf data(intJ, 2) = 3 Then
intCount(3) = intCount(3) + 1
ReDim Preserve D3(intCount(3))
D3(intCount(3)) = data(intJ, 1)
ElseIf data(intJ, 2) = 4 Then
intCount(4) = intCount(4) + 1
ReDim Preserve D4(intCount(4))
D4(intCount(4)) = data(intJ, 1)
ElseIf data(intJ, 2) = 5 Then
intCount(5) = intCount(5) + 1
ReDim Preserve D5(intCount(5))
D5(intCount(5)) = data(intJ, 1)
ElseIf data(intJ, 2) = 6 Then
intCount(6) = intCount(6) + 1
ReDim Preserve D6(intCount(6))
D6(intCount(6)) = data(intJ, 1)
End If
Next
Dim cht As Chart
Set cht = ActiveChart
Dim ax1 As Axis
Set ax1 = cht.Axes(1)
Dim ax2 As Axis
Set ax2 = cht.Axes(2)
ax1.MinimumScale = 0
ax1.MaximumScale = 7
ax2.MinimumScale = -0.1
ax2.MaximumScale = 0.4
ax2.ReversePlotOrder = True
If cht.Shapes.Count > 0 Then
For intI = cht.Shapes.Count To 1 Step -1
cht.Shapes(intI).Delete
Next
End If
DrawBoxplot D1, intCount(1), cht, 255, 0, 0, 1, 0.5, False
DrawBoxplot D2, intCount(2), cht, 0, 255, 0, 2, 0.5, False
DrawBoxplot D3, intCount(3), cht, 0, 0, 255, 3, 0.5, False
DrawBoxplot D4, intCount(4), cht, 255, 255, 0, 4, 0.5, False
DrawBoxplot D5, intCount(5), cht, 0, 255, 255, 5, 0.5, False
DrawBoxplot D6, intCount(6), cht, 255, 0, 255, 6, 0.5, False
End Sub
运行完整代码生成类似图5-23的散点箱形图。[大谦Excel,dqexcel点com]