饼图就是把一个圆按照数据的比例划分成若干部分,大家应该都见过。饼图的形状类型是XL_CHART_TYPE.PIE,所以根据前面的画图经验,创建一个ChartData然后把数据添加进去,应该就能得到饼图了,看起来好像不是很难,代码如下:
from pptx import Presentation
from pptx.chart.data import ChartData
from pptx.enum.chart import XL_CHART_TYPE
from pptx.util import Cm
chart_data = ChartData()
chart_data.categories = ['Q1','Q2','Q3','Q4']
sale_volume = [36.6,21.1,15.9,20.4]
chart_data.add_series('数码娱乐',sale_volume)
ppt = Presentation()
slide = ppt.slides.add_slide(ppt.slide_layouts[6])
x = y = Cm(3)
width = Cm(20)
height = Cm(10)
chart = slide.shapes.add_chart(
XL_CHART_TYPE.PIE,x,y,width,height,chart_data
).chart
ppt.save("./ppt_ files/test.pptx")
果然不是很难,执行代码之后确实可以得到一个饼图,得到的饼图如图8-9所示。
不过这个饼图确实简单得过分了,除了知道它是一个被分成四份的饼图,其他信息都没有,所以我们还需要改进,至少要把图例显示出来吧,另外我们还可以把每个部分的占比情况给显示出来,代码如下:
from pptx import Presentation
from pptx.chart.data import ChartData
from pptx.enum.chart import XL_CHART_TYPE,XL_LEGEND_POSITION
from pptx.enum.chart import XL_DATA_LABEL_POSITION
from pptx.util import Cm
chart_data = ChartData()
chart_data.categories = ['Q1','Q2','Q3','Q4']
sale_volume = [36.6,21.1,15.9,20.4]
percent = [volume / sum(sale_volume) for volume in sale_volume]
print(percent)
# 输出:[0.3893617021276596,0.224468085106383,0.16914893617021276,
0.21702127659574466]
chart_data.add_series('数码娱乐',percent)
ppt = Presentation()
slide = ppt.slides.add_slide(ppt.slide_layouts[6])
x = y = Cm(3)
width = Cm(20)
height = Cm(10)
chart = slide.shapes.add_chart(
XL_CHART_TYPE.PIE,x,y,width,height,chart_data
).chart
chart.has_legend = True
chart.legend.position = XL_LEGEND_POSITION.BOTTOM
chart.plots[0].has_data_labels = True
data_labels = chart.plots[0].data_labels
data_labels.number_format = '0%'
data_labels.position = XL_DATA_LABEL_POSITION.OUTSIDE_END
ppt.save("./ppt_ files/test.pptx")
我们已经会了图例的设置,只要把Chart对象的has_legend属性改为True就行了,关键是还需要特别学一下显示饼图的百分比。首先,我们要提前算好数据的比例,添加系列的时候我们就传入算好的百分比而不是原始数据,因为饼图本来就是按照百分比显示的,所以我们把数据变成百分比之后显示的饼图比例是不会发生变化的。
饼图其实是一个PiePlot对象,我们通过chart对象的plots[0]拿到第一个PiePlot对象(本例中只有一个),先把PiePlot对象的has_data_labels属性改为True,它控制是否显示数据标签,然后再访问PiePlot对象的data_labels属性获取到数据标签,然后调用数据标签的number_format属性修改数据的显示格式,调用数据标签的position属性修改位置。上面代码的最后效果如图8-10所示。