iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 28
0
AI & Data

看對話學 Python 資料分析,用情境故事帶你入門系列 第 28

Day-28 用 Python 製作 PPT 投影片,一鍵搞定!(下)

  • 分享至 

  • twitterImage
  •  


就讓我們用 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 囉!


上一篇
Day-27 用 Python 製作 PPT 投影片,一鍵搞定!(上)
下一篇
Day-29 Python 資料分析自學的正確心態
系列文
看對話學 Python 資料分析,用情境故事帶你入門30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言