學習使用 Matplotlib 來把資料視覺化吧! Licensed by Adobe Stock
Meiko:「Hey,Jason 你說你要跟我講用 Python 畫圖觀察資料的方式,你打算教我什麼啊?」
Jason:「先想一下,平常在公司老闆請做銷售報表的時候,他們都會想看到什麼?」
Meiko:「歐,一般會想要看每天銷售量的變化吧?然後可能會想知道主力產品銷售的數目,然後因為銷售跟時間有很大的關聯性,通常都是週末銷售的數字會比較漂亮!歐,我想起來,這樣跟你前兩天跟我講的人力成本會有關係,訂單少的那幾天,也許就不用那麼多服務生了!」
Jason:「Okay,那我整理一下,我們可能會從幾個方向來看資料,比如說,可以用長條圖看每天銷售的狀況,可以用圓餅圖知道主力產品之間銷售的比例關係,可以用折線圖看看週間和週末的趨勢。」
Meiko:「哇,那我們趕快開始吧!」
Jason:「別急,拿到資料我們一樣先用.head()
的方式,了解一下資料有哪些欄位。再用.describe()
了解一下數值裡面的最大、最小和平均值。」
我大寶寶拉請到這個連結下載檔案後,再解壓縮,並且上傳到自己的 Colab 檔案上傳區,跟Day-20上傳 json 檔案是一樣的做法。
import pandas as pd
pdCurryInfo=pd.read_excel("currySalesAndServiceInfo_Total.xlsx",sheet_name="Sheet1")
pdCurryInfo.head()
Meiko:「看起來這份資料比前兩天的資料再多了 dayTime 這個欄位,MON 是什麼意思?」
Jaosn:「這是餐廳老闆報表,是星期一到星期日的代稱,會用三個字的簡寫代表英文星期幾的意思?MON 是星期一、TUE 是星期二 依此類推...SUN 就是星期天囉!」
Meiko:「好唷,那我們再來看.describe()
有什麼有用的資訊?」
pdCurryInfo.describe()
Jason:「你看平均消費大約是 182元左右,然後顧客對於服務的品質評價還不錯,平均是 4 顆星...」
Meiko:「但好像就沒辦法直接看到銷售的資訊?」
Jason:「哈,因為這就是你需要做的工作拉!那我們就從代表銷售量的長條圖開始吧!在 Python 裡面有一個套件叫做 matplotlib,我們可以先引入 matplotlib 並且使用.pyplot
來畫圖!」
import matplotlib.pyplot as plt
x_labels = ['A','B','C']
sales_num = [120,90,60]
plt.bar(x_labels,sales_num)
plt.show()
Meiko:「原來這樣就能畫出一張長條圖了呀!不過我看不太懂!」
Jason:「它其實有跡可循的拉,比如說我們先把 x 軸,和 y 軸想要表達的資料準備好,x_labels
表示有三種品項 A、B、C,然後針對這 3 種品項,我們有他們對應的銷售資料sales_num
,接下來就是用到plt.bar(x,y)
這個方法,把前述x_labels
放到 x 的位置,把sales_num
放到 y 的位置,最後再用plt.show()
的方式,就能畫出圖來囉!」
Meiko:「真的耶,一點都不難!」
Jason:「那接下來就換你拉,請你把日式餐廳一週裡每天的訂單數,用長條圖畫出來!」
Meiko:「一週裡每天的訂單數,那我要先去把這個資料找到才行,不過 x 軸的資訊好像比較簡單,我先做這個好了!先把星期一到星期天的英文名列出來。」
weekNameList=['MON','TUE','WED','THU','FRI','SAT','SUN' ]
Jason:「接下來就是 y 軸的資料囉,你還記得可以用什麼嗎?」
Meiko:「應該可以用.group_by
吧!剛好已經有每天的資料,我可以先用這個欄位來分開。」
eachDay=pdCurryInfo.groupby('dayTime')
eachDay.size()
Meiko:「我要怎麼印出特定某一天有多少訂單啊?」
Jason:「你記得.get_group
嗎?你可以把剛剛分好的 eachDay 接著用.get_group(某一天)
的方式,去把那天的訂單數印出來!」
len(eachDay.get_group("MON"))
Meiko:「歐,所以我們有星期一的資料,那代表如果我把 weekNameList 裡面每一天都跑過,就可以得到一週的資料了!」
Jason:「所以,應該會長這個樣子!我先幫你把整理資料的部份做完了,接下來圖表的部分就交給你了!」
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)
print (weekName,order_num)
Meiko:「等一下,你多寫了一個order_num_list
是做什麼用的?」
Jason:「那是為了存你前一個步驟,把特定日期的order_num
裡面的值,因為它是每天的訂單數量這樣我們接下來就可以把這個值當作是 y 軸的內容!」
Meiko:「Okay,那我知道了,x 軸是weekNameList
,那麼 y 軸就是order_num_list
囉,那我照你上面的例子把plt.bar()
的內容寫出來,再用plt.show()
印出來!」
import matplotlib.pyplot as plt
weekNameList=['MON','TUE','WED','THU','FRI','SAT','SUN' ]
plt.bar(weekNameList,order_num_list)
plt.show()
Jason:「不錯唷,馬上就印出來了!」
Meiko:「不過,Jason,一般圖表不都是有橫坐標、縱座標的名稱嗎?這張圖好像少了耶什麼?」
Jason:「沒錯,差了一點資訊,在 matplotlib 裡面,會有title
代表標題,xlabel
和ylabel
就分別是 x 軸和 y 軸的名稱。我們再補充一下資訊。」
import matplotlib.pyplot as plt
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.show()
Meiko:「這樣就清楚多囉!」
Jason:「那我們繼續囉,現在有一整週的訂單資料,接下來我們就要來看,日式餐廳裡面每個主餐的銷售量囉!」
Meiko:「這樣老闆就有辦法知道哪個主餐賣得比較好,看是否要調整菜單?」
Jason:「這是一個不錯的方向唷!」
Meiko:「那我一樣用group_by
把content
整理一下,」
maindish=pdCurryInfo.groupby('content')
maindish.size()
Meiko:「恩,我可能還要知道一下日式餐廳的主餐有哪些?目前看來每個餐點都有『甘口』、『辛口』的差別。」
Jason:「主要有 4 種主餐『牛肉咖喱』、『豬排咖哩』、『雞肉咖哩』、『可樂餅咖哩』!」
content_type=['牛肉咖喱','豬排咖哩','雞肉咖哩','可樂餅咖哩']
Meiko:「可是因為我們'content'
這個欄位裡面是把口味直接寫在一起,要想一下怎麼知道特定主菜如何計算?」
Jason:「我幫你整理一下,在這一週裡面 4 種主菜,分別賣出的份數如下...」
content_total=['甘口牛肉咖喱','辛口牛肉咖喱','甘口豬排咖哩','辛口豬排咖哩','甘口雞肉咖哩','辛口雞肉咖哩','甘口可樂餅咖哩','辛口可樂餅咖哩']
maindish_count_list=list()
beef=0
pork=0
chicken=0
croquette=0
for i in range(len(content_total)):
content=content_total[i]
maindish_count=len(maindish.get_group(content))
maindish_count_list.append(maindish_count)
print (content,maindish_count)
order_sales=[187,158,176,147]
Meiko:「所以我們接下來就可以來畫圓餅圖囉!」
Jason:「哈哈,對啊,我把剛幫你整理出來 4 種主菜的銷售狀況,搭配標籤labels
就可以用plt.pie
去畫出來一個完整的圓餅圖囉!」
labels = ['beef','pork','chicken','croquette'] # 製作圓餅圖的類別標籤
order_sales=[187,158,176,147]
maindish_dist = order_sales # 製作圓餅圖的數值
plt.pie(maindish_dist, # 數值
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.show()
Meiko:「哇,看起來也蠻專業的耶!」
Jaosn:「當然囉,matplotlib 相當完整,所以想要表達的內容,應跟都可以在 plt.pie()參數裡面寫出來,該怎麼設定你就照著裡面的做法就可以囉!」
Meiko:「看來一點也不難麻,我想餐廳老闆最重視的應該是業績吧,要怎麼樣從資料裡面把業績整理起來給老闆看?」
Jason:「沒錯,你可以用每天來區分,我教你用一招很快的方式找到星期一的銷售量!」
pdCurryInfo[pdCurryInfo['dayTime']=='MON'].price.sum()
Meiko:「歐,Jason 只要一行程式碼就搞定了呀!」
Jason:「對啊,我先用判斷是,先去 pdCurryInfo
裡面當欄位dayTime=='MON
代表我要看星期一的時間,接著外層有一個pdCurryInfo[內層判斷].price.sum()
就是去找到'price'
欄位,再用.sum()
累加起來,一行就搞定了啊!」
Meiko:「那我就要接著用for-loop
把每一天的銷售量寫出來囉!」
weekSales=list()
for i in range(len(weekNameList)):
weekName=weekNameList[i]
weekSale=pdCurryInfo[pdCurryInfo['dayTime']==weekName].price.sum()
weekSales.append(weekSale)
print (weekSales)
Jason:「最後,很快地,我們也可以用plt.plot(x,y)
把一週的銷售量找出來!x 軸就可以帶入weekNameList
,然後 y 軸就可以帶入weekSales
!」
plt.plot(weekNameList,weekSales)
plt.title('Week Sales')
plt.xlabel('Week Day')
plt.ylabel('Sale')
plt.show()
Meiko:「那如果我想合併訂單和銷售量的資訊,要怎麼辦?說不定可以看出來什麼趨勢?」
Jason:「可以呀,不過要多做一點事就是...像下面這樣,我們要用到.sublplots()
的方式,設定fig
還有兩個 axis,分別是 ax1 和 ax2 這樣我們才能畫出 2 個不同的 Y 座標軸。當然囉,因為 X 座標軸都是同樣的資訊,我們就不用重新設定!」
#設定資料
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.show()
Meiko:「哇,這張圖蠻厲害的,同時有訂單數還有銷售額!我看到有.twinx()
這是什麼?」
Jason:「它就是告訴程式說我要在同一張圖有 2 個不同的 y 軸座標!」
Meiko:「那[tl.set_color('r') for tl in ax2.get_yticklabels()]
這個好像自兩段程式碼都有出現?」
Jason:「這個只是要讓左邊的 y 軸座標顏色和長方圖一樣,右邊的 y 軸座標顏色和折線圖一樣囉!」
Meiko:「這樣我就完全懂了,那這張圖綁在一起看,能夠看出什麼額外的資訊嗎?」
Jason:「明顯看到訂單數量是和銷售額可能有正相關,如果想知道更細部的資訊,可能要有多幾個星期的資料!但是通常老闆看到這樣的現象,就知道應該要想辦法多贈加訂單,就可以帶更多生意了!」
Meiko:「說不定老闆已經開始思考跟外送平台合作,多做一些外送的生意,就可以增加訂單了!」
Jason:「不錯唷!這樣不需要增加餐廳內的空間,還可以增加訂單數量!真是一個好方法,」
我大寶寶~拉,今天我們談了用 Matplotlib ,將資料用圖檔的方式呈現出來,透過長方圖、圓餅圖及曲線圖,把餐廳的銷售資料做一番整理,除了學會如何撰寫程式畫出圖檔之外,過程中我們也做了一些資料處理的工作,這些必要的先期準備工作做完,才做得到資料視覺化。此外,重點還是觀察這些資料後,能夠做出什麼商業決策,這才是最有價值的一部分唷!
歡迎登入留言跟我分享你的想法唷!(登入不麻煩,點一下 FB 登入就可以留言了!)
1.喜歡這樣方式學 Python 的朋友請留言『+1』
2.如果前面的內容忘記了,趕快看一下大寶寶這一系列的看對話學 Python 資料分析,用情境故事帶你入門的列表!就能夠繼續 Happy Coding 囉!