如何用視覺化呈現廣告效益? 電商產業廣告效益分析實戰(附Python 程式碼)
資料科學人員需要進行資料呈現時,比起直接提供平均數、中位數、最大最小值等敘述性指標,盒鬚圖往往是更受歡迎的選擇。
盒鬚圖,又稱為箱型圖,是一種檢視或者是比較資料分散程度時,相當好用直觀的一種統計呈現圖。它可以將將資料的分佈,如:最大值、最小值、中位數、第一四分位以及第三四分位數等統計量一目了然地呈現出來,協助管理者或資料接收者掌握狀況;也能讓我們在進行統計檢定及迴歸預測前,能對資料有初步的決策參考。
本次使用的資料集檔名為「sales_data.csv」,本文將透過產品系列在不同月份的廣告效益,利用盒鬚圖來呈現,帶您感受這個好用的視覺化呈現方式。
一、基本資料引入
首先,將本次會使用到的套件包以及分析資料(點我下載)引入,如程式碼1所示:
程式碼1:
import pandas as pdimport osfrom collections import Counterimport heapqimport plotly.offline as pyimport plotly.graph_objects as godata = pd.read_csv("new_salesdata.csv")
產出如圖1:
隨後,將本次製圖不需使用到的資料欄位,如顏色、性別、年齡等,透過程式碼2移除。
程式碼2:
data = data.drop(columns = list(data.filter(regex='Unnamed: 0|顏色|會員|產品|性別|年紀|尺寸')))
產出如圖2:
二、基礎資料處理
我們將針對「系列」以及「廣告名稱」著手進行處理。
(一) 系列
由於該電商資料共有一千種以上的系列,每種系列常用的廣告宣傳方式以及廣告可以帶來的效益都有所不同。因此為了方便學習理解,本文只會使用「系列4」的資料用來製圖,透過下方程式碼3可將「系列4」以外的資料篩選掉:
程式碼3:
data = data[ data ['系列'] == '系列4']
產出如圖3:
篩選完之後可透過「Variable explorer」看到,資料集中「data」的資料成功從35萬筆左右篩選到剩下11059筆了。
(二) 廣告名稱
展開資料集「data」可以發現,該資料集在廣告方面的記載十分詳盡,舉例來說:光是廣告系列「KDPOD」就有「qrtist」、「chiciMT」、「select」、「chicihey」…等細項分支。若要考慮到如此大量的廣告種類,除了資料集被大量廣告平分下來會有個別資料過少問題,龐大的類別也會使資料處理及呈現變得雜亂,因此在進行資料呈現時只考慮廣告「系列」,而忽略了廣告「細項」。
此時,則需要透過程式碼4,使用for迴圈逐一抓取資料,並依照廣告資料格式,使用「split」功能將廣告名稱依照「_」切分開來,並取出系列名稱。
程式碼4:
for i in range(0,len(data['廣告代號all'])):a = data['廣告代號all'][i].split('_')[1]data['廣告代號all'][i] = a
產出如圖4:
三、進階資料處理-挑選主力廣告
即使已經忽略廣告的細部分支,展開資料集仍可發現一些問題:
1. 廣告種類依舊五花八門,可能導致資料展示及分析困難
2. 資料集中少數的廣告系列佔據了大部分的資料筆數
透過程式碼5,可幫助掌握系列4總共使用了幾種系列的廣告:
程式碼5:
len(data['廣告代號all'].unique())
產出如下:
36
從產出可看到,系列4在行銷廣宣上一共使用了36系列的廣告。接著使用「Counter」功能,可協助我們計算不同廣告總共使用的頻率分別為多少,如程式碼6所示,製作出頻率清單「count_list」:
程式碼6:
count_list = Counter(data['廣告代號all'])
產出如圖5:
緊接著,透過程式碼7,將「count_list」整理成DataFrame格式,以利閱讀,如下所示:
程式碼7:
count_list = pd.DataFrame.from_dict(count_list,orient='index').reset_index() # 轉換為DataFrame形式count_list = count_list.rename(columns = {'index' : '廣告名稱', 0: '樣本數'}) # 重新命名欄位名稱
產出如圖6:
透過「count_list」可以看到,除了少數幾款廣告系列有800筆以上的使用頻率以外,大部分的廣告系列皆只有個位數或是十位數的使用頻率,不適合用來做資料分析,因此本次分析將只使用頻率前三名的熱門廣告系列進行繪圖分析。
透過程式碼8,使用套件包「heapq」中的「nlargest」功能,取出最熱門的前三名廣告頻率,寫法如下:
l heapq.nlargest(取到第幾名,資料來源)
程式碼8:
heapq.nlargest(3,list(count_list['樣本數']))
產出如下:
[3780, 1793, 1285]
了解了使用方式之後,我們可以利用產出結果,將第三名的頻率「dead_number」取出來,做為後續篩選是否為熱門廣告系列的門檻,如程式碼9:
程式碼9:
dead_number = heapq.nlargest(4,list(count_list['樣本數']))[2]
產出如下:
1285
有了熱門廣告系列第三名的頻率之後,便可以透過邏輯運算子,將使用頻率小於「dead_number」的廣告系列納入清單「dead_list」內,準備進行排除,如下程式碼10:
程式碼10:
dead_list = count_list[count_list['樣本數'] < dead_number]
產出如圖7:
透過程式碼11,把資料集「data」內的非熱門廣告系列資料,透過「dead_list」逐一刪除,只留下使用熱門廣告的資料,共6858筆。
程式碼11:
for i in dead_list['廣告名稱']:data= data[~data['廣告代號all'].isin([i])]
產出如圖8:
有趣的是,在上方程式中有使用了一個「~」的符號,代表的意思為「Not」,只能放在變數前,做為輔助記號。
比起逐一將每一種熱門廣告從資料集「data」中取出並且合併,使用「~」將非熱門廣告的資料排除是比較有效率的做法,十分推薦。
最後,我們可以注意到熱門廣告中出現了「自然流量」,自然流量並非我們可控的廣告項目,因此透過程式碼12將其從資料集「data」中排除,如下:
程式碼12:
data = data[~data['廣告代號all'].isin(['自然流量'])]
產出如圖9:
四、進階資料處理-不同廣告每期帶來的淨利
到目前為止,資料處理差不多完成7成了,要將資料用來繪圖之前,還得計算出資料集的「淨利」,並加以統整出不同廣告在每一期(月份)為系列4帶來的利潤為多少。
首先透過「split」功能,將「訂單時間」根據「-」做切分,並取出「月份」,回存至資料集「data」中。如程式碼13所示:
程式碼13:
data['月份'] = data['訂單時間'].str.split('-', expand = True)[1].astype(int)
產出如圖10:
「月份」將會用來在製圖時,做為X座標。
接著用一樣的手法,透過「split」功能取出資料的「年月」後並回存至資料集「data」中,用以區分該筆資料的交易時間為哪一期,如下程式碼14:
程式碼14:
data['年月'] = (data['訂單時間 '].str.split('-', expand = True)[0] + data['訂單時間'].str.split('-', expand = True)[1]).astype(int)
產出如圖11:
透過程式碼15,利用產品的「單價」減掉產品的「成本」,取得「淨利」,並回存至資料集「data」中。
程式碼15:
data['淨利'] = data['單價'] - data['成本']
產出如圖12:
透過程式碼16,將資料集「data」的多餘欄位去除。
程式碼16:
data = data.drop(['單價', '成本', '系列', '訂單時間'], axis=1)
產出如圖13:
在前面我們透過資料處理取出了辨識期別的「年月」欄位以及利潤欄位「淨利」,接下來透過程式碼17,使用「pandas」中的群組功能「groupby」,將資料集「data」內的資料根據「廣告」、「月份」以及「年月」進行群組,並計算出淨利總和,如下:
程式碼17:
data = data.groupby(['廣告代號all', '月份', '年月'])['淨利'].sum()
產出如圖14:
透過程式碼18,將「data」從「Series」型態再次轉換為「DataFrame」型態。如下:
程式碼18:
data = data.to_frame().reset_index()
產出如圖15:
最後,在進行繪圖之前,將已經不需再使用的「年月」欄位移除,並新增「count」欄位,每筆資料的「count」欄位皆為1。
由於不同產品系列有不同的銷售期間,因此有可能會有些期數沒有任何該產品系列的交易數據。舉例來說:產品系列X於2017年上市,並於2018年底停售,若我們想了解該產品在1月的平均利潤,應該除以兩年而非四年(本原始資料時間範圍為2016~2019年)。透過count的加總,我們可以很清楚不同年度的同一個月份共有幾筆資料,並做為計算平均時的分母。如下程式碼19:
程式碼19:
data = data.drop(['年月'], axis=1)data['count'] = 1
產出如圖16:
五、繪圖
經過了一大番努力過後,終於可以將處理完後的資料繪圖產出啦!透過程式碼20可先設置空白畫布,並透過for迴圈,在上面逐月繪製盒鬚圖:
程式碼20:
fig = go.Figure() # 設定空白畫布colors_box = ['#3366CC', '#DC3912'] # 設定盒子顏色# 繪製盒鬚圖for i in range(0, len(data['廣告代號all'].unique())):fig.add_trace(go.Box(y = data[data['廣告代號all'] ==data['廣告代號all'].unique()[i]]['淨利'],x = data[data['廣告代號all'] ==data['廣告代號all'].unique()[i]]['月份'],name = str(data[data['廣告代號all'] ==data['廣告代號all'].unique()[i]]['廣告代號all'][0:1].values[0]),marker_color= colors_box[i]))
盒鬚圖內的設定如下:
y:盒鬚圖的Y軸,在這邊指的是「平均淨利」
x:盒鬚圖的X軸,在這邊指的是「月份」
name:類別名稱,在這邊是依據「廣告類別」區分
marker_color:盒子的顏色,如清單「colors_box」所示
設定完了盒鬚圖之後,接著會透過程式碼21繪製上平均線,如下所示:
程式碼21:
adlist = list(data['廣告代號all'].unique()) # 廣告名稱清單color_line = ["royalblue" , "firebrick"] # 設定線條顏色# 畫平均線for i in range(0,len(adlist)):ad = adlist[i]colour = color_line[i]meanlist = [] # 平均axislist = [] # 月分for ii in range(1,13):axislist.append(ii)total = data[data['廣告代號all'] == ad][data['月份'] == ii]['淨利'].sum()counts = data[data['廣告代號all'] == ad][data['月份'] == ii]['count'].sum()aver = total/countsmeanlist.append(aver)if ii == 12:fig.add_trace(go.Scatter(x= axislist,y= meanlist,mode="lines+markers",textfont=dict(family="sans serif",size=16,color="royalblue"),line=dict(color=colour, width=2),))
平均線的繪製程式共有三層,看起來很複雜,讓我們透過拆解的方式來逐一檢視:
(一) 第一層
將廣告清單「adlist」放入for迴圈中分別進行繪製準備(設置好用來放X軸月份的清單「axislist」以及放Y軸資料的平均淨利清單「meanlist」),因此平均線的繪製順序會如同「adlist」內的資料順序一樣,先畫「KDP」再畫「critei」。
(二) 第二層
新增第二層for迴圈,設定一個範圍1~12的迴圈,分別計算每個月的平均淨利,並將「月份」新增至清單「axislist」中;「平均淨利」新增至清單「meanlist」中。
(三) 第三層
設定一個判斷式,當迴圈逐一從1月計算平均至12月結束後,便將該廣告的「每月廣告平均淨利線」繪製出來。
資料都輸入完之後,便可設定布景並且產出了,如下程式碼22、程式碼23:
程式碼22:
# 設定佈景主題(字體、大小、背景等)fig.update_layout(title={'text': "<b>BoxPlot-系列四 廣告效益分析</b>",'y':0.95,'x':0.5,'xanchor': 'center',},yaxis_title='Profit',xaxis={'title': 'Month','tickmode': 'linear'},width=1800,height=960,boxmode='group',font=dict(family="Courier New, monospace",size=20,color="lightslategrey"))
程式碼23:
# 另存html檔py.plot(fig, filename='BoxPlot-系列四 廣告效益分析', auto_open=True)# 另存圖檔fig.write_image("BoxPlot-系列四 廣告效益分析.png")
終於產出最後的盒鬚圖,如圖17:
(四)小結
我們可針對產出的圖片做初步的熱門廣告效益分析:
「critei」在九月時,相較於「KDP」可讓「系列4」有較好的淨利效果,因此在九月時對「系列4」加強「critei」廣告應該可以產生更好的獲利效果。
而有些月分則較難從目測比較廣告的好壞,如:以5月的資料來說,雖然「KDP」的淨利涵蓋範圍遠高於「critei」的淨利涵蓋範圍,應該會有比較好的效果,但使用「critei」時的淨利範圍比較集中,可以得到較好的控制效果,因此難以推論誰好誰壞。
有沒有發現上面的結論不斷出現「應該」呢?那是因為在進行決策參考時,若沒有一個公允的指標或檢定來進行判斷的話,資料科學人員所能歸納出的結果往往會偏於主觀想法。
因此,資料科學從業人員經常需要依母體分佈,用不同的統計檢定對資料進作假設及驗證,將這些檢定應用至商務個案中,創造出準確且值得信賴的決策指標。
若是喜歡我的文章,請多為我拍拍手,我也會持續分享不同的統計檢定如何應用在商務個案~
完整程式碼:https://reurl.cc/7ol2yy
作者:徐子皓(臺灣行銷研究特邀作者)、鍾皓軒(臺灣行銷研究有限公司創辦人)
更多實戰案例及情境好文推薦
我的競爭優勢? 視覺化口碑定位雷達圖輕鬆搜出來!(附實現程式碼)
我的競爭優勢? 視覺化口碑定位雷達圖輕鬆搜出來!(附實現程式碼) 企業競爭者的調查方式 vs 網路特性 企業的品牌以及形象,是企業一向非常重
好用的 Function 操作-模組化商務程式的整合者(附Python 程式碼)
好用的 Function 操作- 模組化商務程式的整合者(附Python 程式碼) Python是資料科學家進行分析的重要工具。在學習Pyt
還在手動上字幕? Python 幫您完成「自動化上字幕」 — 案例分享(附Python程式碼)
還在手動上字幕? Python 幫您完成「自動化上字幕」 - 案例分享(附Python程式碼) Youtuber、數位媒體製作人、會議記錄者