就讓我們用 Python 做出來的投影片,進行簡報吧!Licensed by Adobe Stock
想要做資料分析師?做好報告也是非常重要的,但是如何能夠有效率的做出足夠傳達資訊的投影片?現在用 Python 也可以做到!
Meiko:「誒,Jason,雖然昨天你有帶我做了一個示範的投影片,可是真的做出資料分析的投影片,可沒這麼簡單呀!」
Jason:「對啊,所以我趁你昨天回家的時候,把先前我們在Day-25做的資料稍微整理了一下,然後就像一般我們做開會投影片一樣,會做大綱,說明這次開會要討論的項目,最後再加上臨時動議,這樣就跟完整的報告很像囉!」
Meiko:「哇,Jason,上面 6 頁看起來,根本就像人做的,完全看不出來是 Python 寫的耶!」
Jason:「對啊,這就是 Python 厲害的地方。」
Meiko:「不過這段程式碼也太長了吧?我可能沒辦法一下消化!」
Jason:「沒關係,其實這裡面的邏輯,跟我們一般在做投影片很像,都會有一個首頁、接著大綱、然後內頁就會依照大綱出現,最後在來個臨時動議!」
Meiko:「好吧,我來研究一下!」
Jason:「我覺得一開始比較難的是大綱頁,因為他把paragraph
的方式延伸,所以新增了多個text_frame
。從body_shape = shapes.placeholders[1]
開始,它去找在投影片中,小標的位置,因為在大綱中我們會把後面的內頁內容都填上,這些內容我們先用一個paragraph_strs
的串列儲存。」
Meiko:「歐,就是預先寫好大綱的意思。」
Jason:「對啊,因為我們在大綱有 4 個點要討論,所以我們產生text_frame 之後body_shape.text_frame
設定成tf
再用tf.clear()
把目前的text_Frame
都清空之後才開始。」
Jason:「接著,概念就是我們先產生tf.paragraph[0]
,也就是第一大點,然後接著用for-loop
把剩下的paragraph
都加上去。」
#============= 大綱頁 ==========
text1="大綱"
title_slide_layout = prs.slide_layouts[1]
slide = prs.slides.add_slide(title_slide_layout)
shapes = slide.shapes
title_shape = shapes.title
title_shape.text = text1
#投影片內第一大點
paragraph_strs = [
'一週銷售長方圖',
'一週主餐圓餅圖',
'一週銷售量與訂單關係',
'臨時動議'
]
body_shape = shapes.placeholders[1]
tf = body_shape.text_frame
tf.clear()
p = tf.paragraphs[0]
p.text = paragraph_strs[0]
for para_str in paragraph_strs[1:]:
p = tf.add_paragraph()
p.text = para_str
Meiko:「歐,你這樣講我就比較懂意思了!」
Jaosn:「再來就是我把add_slide(prs, layout, title,img,text1,text2,text3)
這個函式做了一些調整。增加了text1
~text3
的變數,因為我們的內頁都是用同樣的slide
格式,所以我這邊把這個函式變得更模組化,把每張投影片要輸入的文字拿出來用text1
~text3
做代表。」
Meiko:「歐,原本直接打在函式裡面的文字就被替代了!」
Jason:「對啊!再來講最後一個變動就是在內頁第二頁的部分,我們看到一個新增計算的部分。」
Meiko:「誒,這邊把好多你先前講的技巧整理在一起有串列list
迴圈for-loop
字典dictionary
判斷式if-else
」!根本就是滿漢全席了!」
Jason:「對啊,就在這短短幾行程式,就把先前教的內容全部都複習過一次了!」
#新增計算
contentList=list()
maindish_list=list()
localDic={}
localDic['beef']=0
localDic['pork']=0
localDic['chicken']=0
localDic['croquette']=0
for i in range(len(content_total)):
content=content_total[i]
stuff = content.decode('utf-8')
print "%d,%s"%(i,stuff)
maindish_count=len(maindish.get_group(stuff))
maindish_count_list.append(maindish_count)
if '牛肉' in stuff:
localDic['beef']+=maindish_count
elif '豬排' in stuff:
localDic['pork']+=maindish_count
elif '雞肉' in stuff:
localDic['chicken']+=maindish_count
elif '可樂餅' in stuff:
localDic['croquette']+=maindish_count
maindish_list.append(localDic['beef'])
maindish_list.append(localDic['pork'])
maindish_list.append(localDic['chicken'])
maindish_list.append(localDic['croquette'])
Meiko:「好厲害,不過我好像漸漸懂了,反正不懂的地方,就把它列印出來,熟悉整個運算邏輯就是!」
Jason:「不錯唷,最後講一個在下面.plt
的部分,會看到我有用一個plt.clf()
,因為我們有畫多張圖檔,所以每畫一張之前,要先把前面的清掉,程式才不會重複話在同一張圖上!」
Meiko:「歐!這樣也蠻合理的呀!」
Jason:「好囉,那下面就是全部的程式碼,只要在命令提示列上一個鍵執行,你就可以產生需要的報告投影片拉!」
Meiko:「Yes!這樣好輕鬆啊!」
# -*- coding:utf-8 -*-
from pptx import Presentation
import matplotlib.pyplot as plt
from pptx.util import Inches
import pandas as pd
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
#開啟新的簡報物件
prs = Presentation()
#建立簡報檔第一張頁面物件
title_slide_layout = prs.slide_layouts[0]
#增加一張簡報
slide = prs.slides.add_slide(title_slide_layout)
#設定第一張簡報的標題
title = slide.shapes.title
title.text = "餐廳銷售量週報"
#設定第一張簡報的副標題
subtitle = slide.placeholders[1]
subtitle.text = "作者:Meiko 2020/10/01"
#將簡報物件存檔
pdCurryInfo=pd.read_excel("currySalesAndServiceInfo_Total.xlsx",sheet_name="Sheet1")
def add_slide(prs, layout, title,img,text1,text2,text3):
slide = prs.slides.add_slide(layout)
shapes = slide.shapes
#投影片標題
title_shape = shapes.title
title_shape.text = text1
#投影片內第一大點
body_shape = shapes.placeholders[1]
tf = body_shape.text_frame
tf.text = text2
#投影片內第二階層小點
p = tf.add_paragraph()
p.text = text3
p.level = 1
# show the figure
left = Inches(3)
height = Inches(4.5)
left = top = Inches(3)
pic = slide.shapes.add_picture(img, left, top, height=height)
return slide
#============= 大綱頁 ==========
text1="大綱"
title_slide_layout = prs.slide_layouts[1]
slide = prs.slides.add_slide(title_slide_layout)
shapes = slide.shapes
title_shape = shapes.title
title_shape.text = text1
#投影片內第一大點
paragraph_strs = [
'一週銷售長方圖',
'一週主餐圓餅圖',
'一週銷售量與訂單關係',
'臨時動議'
]
body_shape = shapes.placeholders[1]
tf = body_shape.text_frame
tf.clear()
p = tf.paragraphs[0]
p.text = paragraph_strs[0]
for para_str in paragraph_strs[1:]:
p = tf.add_paragraph()
p.text = para_str
#============= 內頁第一頁開始 ===========
eachDay=pdCurryInfo.groupby('dayTime')
eachDay.size()
weekNameList=['MON','TUE','WED','THU','FRI','SAT','SUN' ]
order_num_list=list()
for i in range(len(weekNameList)):
weekName=weekNameList[i]
order_num=len(eachDay.get_group(weekName))
order_num_list.append(order_num)
weekNameList=['MON','TUE','WED','THU','FRI','SAT','SUN' ]
plt.bar(weekNameList,order_num_list)
plt.title("Week Sales")
plt.xlabel('Week Day')
plt.ylabel('Order Count')
plt.savefig('bar_graph.jpg')
img_bar="bar_graph.jpg"
text1='一週銷售長方圖'
text2='該週的銷售量分佈'
text3='分別列出週一~週日每天的訂單數量'
title_slide_layout = prs.slide_layouts[1]
slide = add_slide(prs, title_slide_layout,title ,img_bar,text1,text2,text3)
#============= 內頁第二頁開始 ===========
maindish=pdCurryInfo.groupby('content')
maindish.size()
content_type=['牛肉咖喱','豬排咖哩','雞肉咖哩','可樂餅咖哩']
content_total=['甘口牛肉咖喱','辛口牛肉咖喱','甘口豬排咖哩','辛口豬排咖哩','甘口雞肉咖哩','辛口雞肉咖哩','甘口可樂餅咖哩','辛口可樂餅咖哩']
maindish_count_list=list()
beef=0
pork=0
chicken=0
croquette=0
#新增計算
contentList=list()
maindish_list=list()
localDic={}
localDic['beef']=0
localDic['pork']=0
localDic['chicken']=0
localDic['croquette']=0
for i in range(len(content_total)):
content=content_total[i]
stuff = content.decode('utf-8')
print "%d,%s"%(i,stuff)
maindish_count=len(maindish.get_group(stuff))
maindish_count_list.append(maindish_count)
if '牛肉' in stuff:
localDic['beef']+=maindish_count
elif '豬排' in stuff:
localDic['pork']+=maindish_count
elif '雞肉' in stuff:
localDic['chicken']+=maindish_count
elif '可樂餅' in stuff:
localDic['croquette']+=maindish_count
maindish_list.append(localDic['beef'])
maindish_list.append(localDic['pork'])
maindish_list.append(localDic['chicken'])
maindish_list.append(localDic['croquette'])
print ("----- maindish_count ------")
print (maindish_list)
labels = ['beef','pork','chicken','croquette'] # 製作圓餅圖的類別標籤
plt.clf()
plt.pie(maindish_list, # 數值
labels = labels, # 標籤
autopct = "%1.1f%%", # 將數值百分比並留到小數點一位
pctdistance = 0.5, # 數字距圓心的距離
textprops = {"fontsize" : 16}, # 文字大小
shadow=True) # 設定陰影
plt.axis('equal') # 使圓餅圖比例相等
plt.title("Pie chart of curry sales", {"fontsize" : 18}) # 設定標題及其文字大小
plt.savefig('pie_graph.jpg')
img_pie="pie_graph.jpg"
text1='一週主餐圓餅圖'
text2='該週的圓餅圖分佈'
text3='列出牛肉、豬排、雞肉、可樂餅咖哩的比率'
title_slide_layout = prs.slide_layouts[1]
slide = add_slide(prs, title_slide_layout,title ,img_pie,text1,text2,text3)
#============= 內頁第三頁開始 ===========
weekSales=list()
for i in range(len(weekNameList)):
weekName=weekNameList[i]
weekSale=pdCurryInfo[pdCurryInfo['dayTime']==weekName].price.sum()
weekSales.append(weekSale)
plt.clf()
#設定資料
data1 = order_num_list
data2 = weekSales
t = weekNameList
#Plot graph with 2 y axes
fig, ax1 = plt.subplots()
#畫出訂單數長方圖
ax1.bar(t, data1)
ax1.set_xlabel('Week Day')
# 將資料 1 設定成藍色
ax1.set_ylabel('Order Count', color='b')
[tl.set_color('b') for tl in ax1.get_yticklabels()]
#利用.twinx()在右方畫出 sales 的 y 軸,並劃出銷售額折線圖
ax2 = ax1.twinx()
#Plot a line
ax2.plot(t, data2, 'r-')
# 將資料 2 設定成紅色
ax2.set_ylabel('Sales', color='r')
[tl.set_color('r') for tl in ax2.get_yticklabels()]
plt.title('Sales and Orders')
plt.savefig('twinx_graph.jpg')
img_twinx="twinx_graph.jpg"
text1='一週銷售量與訂單關係'
text2='藍色為訂單數、紅色為銷售量'
text3='可以看出訂單數與銷售量有正比關係'
title_slide_layout = prs.slide_layouts[1]
slide = add_slide(prs, title_slide_layout,title ,img_twinx,text1,text2,text3)
#============= 討論頁 ===========
text1="臨時動議"
title_slide_layout = prs.slide_layouts[1]
slide = prs.slides.add_slide(title_slide_layout)
shapes = slide.shapes
title_shape = shapes.title
title_shape.text = text1
body_shape = shapes.placeholders[1]
tf = body_shape.text_frame
tf.clear()
p = tf.paragraphs[0]
p.text = "討論"
#產生頭影片
prs.save("python_ppt_output.pptx")
我大寶寶~拉,今天我們用 Python 加上前幾天教的 Matplotlib 整合在一份檔案裡面,以及先前所有的基礎程式技巧整理資料,做出一份完整的簡報。當然,實際公司需要的簡報,會比今天談論的還要更多,但是有這樣的技巧,相信各位之後在做投影片整理資料的時候,會多一個選擇!
歡迎登入留言跟我分享你的想法唷!(登入不麻煩,點一下 FB 登入就可以留言了!)
1.喜歡這樣方式學 Python 的朋友請留言『+1』
2.如果前面的內容忘記了,趕快看一下大寶寶這一系列的看對話學 Python 資料分析,用情境故事帶你入門的列表!就能夠繼續 Happy Coding 囉!