二因子變異數分析 — Python實戰:不同廣告與人口變數(地區)如何最佳搭配?(附Python程式碼)

徐子皓 Nash Xu
Marketingdatascience
13 min readDec 9, 2020

在上一篇文章中,我們已經將資料按照廣告類型以及地區各自分成了三類(alist~flist),在單因子變異數的文章中,我們只比較不同「廣告」對於消費者在「平均消費支出」的影響。而在本篇文章中將額外加入地區作為考量,並透過多因子變異數分析進一步評估這三者彼此間的交互影響。

忘了單因子變異分析的文章了嗎?複習一下吧~
單因子變異數分析 — Python實戰:商務資料結構整理(附Python 程式碼)
單因子變異數分析 — Python實戰:如何決定多廣告的優化策略?(附Python 程式碼)

再回顧一下上一篇文章:
二因子變異數分析 — Python實戰:商務資料結構整理(附Python 程式碼)

一、事前檢定

同於先前於單因子變異數分析單元,在開始進行ANOVA檢定之前,要先檢查資料間是否同質以及符合常態分配,透過程式碼1,使用shapiro常態檢定,判斷整理後資料是否有不符合常態的跡象。

程式碼1:

import scipy.stats as st
st.shapiro(alist)
st.shapiro(blist)
st.shapiro(clist)
st.shapiro(dlist)
st.shapiro(elist)
st.shapiro(flist)

產出:

ShapiroResult(statistic=0.9915865659713745,pvalue=0.6819638013839722)
ShapiroResult(statistic=0.9929247498512268,pvalue=0.805463969707489)
ShapiroResult(statistic=0.9802003502845764,pvalue=0.07433854043483734)
ShapiroResult(statistic=0.9931642413139343,pvalue=0.7976954579353333)
ShapiroResult(statistic=0.988785982131958,pvalue=0.4260871410369873)
ShapiroResult(statistic=0.9914966225624084,pvalue=0.718219518661499)

從產出結果來看,這六筆資料的檢定結果P值都大於0.05,因此沒有無法證明這六筆資料有不符合常態的情況。

接下來若要確保這些資料取自變異數相等的母體中,必須透過levene樣本同質性檢定來檢查資料是否有不同值的情況發生,如程式碼2所示。

程式碼2:

st.levene(alist, blist, clist, center='mean')
st.levene(dlist, elist, flist, center='mean')

產出:

LeveneResult(statistic=0.6891243668404422,pvalue=0.5026819827621525)
LeveneResult(statistic=0.25909843233185653,pvalue=0.7718920508101443)

註解:center(中心點)的輸入內容取決於資料分布型態,若資料符合常態分佈,則中心點會設置為「mean(平均值)」;反之若非常態分佈,則中心點設置為「median(中位數)」

從上方的檢定結果來看,無論是根據廣告拆分的資料「alist」、「blist」、「clist」,或是依據地區拆分的資料「dlist」、「elist」、「flist」,P值皆超過廣義認定顯著標準的0.05內,因此沒有證據證明這些資料具有非同質性的跡象。

二、多因子變異數檢定

確保資料無非常態、非同質之虞後,緊接著便可以進行多因子變異數分析了,透過程式碼3,建立出一個分析模組,如下:

程式碼3:

import statsmodels.api as sm
from statsmodels.formula.api import ols
model = ols('消費金額 ~ C(廣告) + C(地區) + C(廣告):C(地區)', data=data).fit()

在本篇文章中所使用的方式為普通最小平方法(Ordinary least squares, OLS),模型內部寫法如下:

ols(應變數~自變數1+自變數2+自變數1:自變數2, data=資料集)

將模組建立完成後,便可以應用至ANOVA檢定中了,透過程式碼4,我們將建立好的模組「model」用以計算出交互作用表,以利了解不同要素對於平均消費金額的影響。

程式碼4:

Results = sm.stats.anova_lm(model)

產出(如圖1所示):

圖 1 要素交叉比較表

圖1的產出結果,提供了十分全面的統計資訊,從自由度(df)、平方誤差和(sum_sq)、均方誤差(mean_sq)、f值(F)到p值(PR(>F))皆詳盡敘述,相信不少讀者已經被各式各樣的指標及專有名詞搞得眼花撩亂了吧?

不用擔心,本篇文章的重點在於掌握每個要素之間是否有顯著地交互影響,因此只會觀察表中的p值(PR(>F)),透過觀察可看到:

  1. 廣告對於平均消費金額的P值為0.0952486,雖沒有在廣義顯著範圍的0.05內,但放寬標準來看算趨近於標準附近,因此本篇文章會進一步後續分析。
  2. 「地區」對於平均消費金額的P值為0.871885,離廣義顯著範圍內的0.05差異極大,因此沒有顯著證據證明不同地區對於平均消費有影響。
  3. 「地區」及「廣告」之間的P值為0.183004,距離顯著範圍內的0.05距離頗大,因此無法證明地區跟廣告之間具有交互影響。(換句話說,該店商不太會依據地區不同投放不同廣告,不同地區投放的廣告很平均)

從表中得到這些資訊後,我們還可以進一步製作出「平均消費支出」在「不同廣告」及「地區」下的財務交叉比較表格,一方面幫助自己更容易掌握顯著每個情境下的狀況;另一方面具有財務資訊的報表也能幫助主管更方便地作為後續的決策評估。

三、財務交叉比較表

首先,將所有的廣告及地區種類透過「.unique()」取出後,再透過「.tolist()」將這些內容轉換為清單形式,以用來做交叉表格的項目名稱,如程式碼5所示:

程式碼5:

var1 = data['廣告'].unique().tolist()
var2 = data['地區'].unique().tolist()
var1
var2

產出:

['廣告1', '廣告2', '廣告3']
['南部', '中部', '北部']

接著,我們要善用for迴圈及if判斷式,來提高分析效率。

將「var1」及「var2」寫成雙重for迴圈,分別計算出不同廣告及地區下的消費平均之後;再透過if判斷式,將計算出的平均根據不同廣告類別歸類至「ad_list」中,如程式碼6所示:

程式碼6:

ad1_list = []
ad2_list = []
ad3_list = []
for i in var1:
for ii in var2:
if i == '廣告1':
ad1_list.append(data[data ['廣告'] == i][data ['地區'] == ii]['消費金額'].mean())
elif i == '廣告2':
ad2_list.append(data[data ['廣告'] == i][data ['地區'] == ii]['消費金額'].mean())
elif i == '廣告3':
ad3_list.append(data[data ['廣告'] == i][data ['地區'] == ii]['消費金額'].mean())

透過程式碼7,可以查看不同廣告在北、中、南部的平均消費金額為何:

程式碼7:

ad1_list
ad2_list
ad3_list

產出:

[17.26818181818182, 17.985434782608703, 16.07414634146341]
[15.5134, 14.253636363636366, 16.893243243243237]
[14.786896551724135, 16.198809523809526, 15.930816326530612]

隨後,將這三筆資料整合成財務交叉資料表,列名稱(index)使用地區名稱「var2」,欄名稱(columns)使用廣告名稱「var1」,如程式碼8所示:

程式碼8:

cross_table = pd.DataFrame((ad1_list, ad2_list, ad3_list),             columns = var2, index = var1)

產出(如圖2所示):

圖 2 地區X廣告-財務交叉比較表

雖然現在我們有了完整的財務報表,以及要素之間的顯著影響度(P值),但仍稱不上是一個好的呈交報告,若沒有將資料進一步視覺化,便很難直觀地在密密麻麻的數字海中,找到具有價值的決策參考。

四、資料視覺化

將資料視覺化的程式技巧,相信各位讀者在閱讀我們行銷資料科學不同主題的文章後,應該功力都很不錯了。以下我們將著重在產出後的資料結果,並進一步分析可以提供給主管的決策參考價值。

透過程式碼9,將用以視覺化之資料導入:

程式碼9:

import plotly.offline as py
import plotly.graph_objects as go
fig = go.Figure()
# 廣告1分布圖
fig.add_trace(go.Scatter(
x= var2,
y= cross_table.iloc[0,:].tolist(),
mode="lines+markers",
textfont=dict(
family="sans serif",
size=16,
color="royalblue"),
line=dict(color='royalblue', width=2),
name = '廣告1'
))
# 廣告2分布圖
fig.add_trace(go.Scatter(
x= var2,
y= cross_table.iloc[1,:].tolist(),
mode="lines+markers",
textfont=dict(
family="sans serif",
size=16,
color="firebrick"),
line=dict(color='firebrick', width=2),
name = '廣告2'
))
# 廣告3分布圖
fig.add_trace(go.Scatter(
x= var2,
y= cross_table.iloc[2,:].tolist(),
mode="lines+markers",
textfont=dict(
family="sans serif",
size=16,
color="green"),
line=dict(color='green', width=2),
name = '廣告3'
))

接著透過程式碼10,為產出的圖片設定版面樣式,包括文字大小、字體、顏色等:

程式碼10:

fig.update_layout(
title={
'text': "<b>廣告效益分析</b>",
'y':0.95,
'x':0.5,
'xanchor': 'center',},
yaxis_title='平均消費金額',
xaxis={
'title': '地區',
'tickmode': 'linear'
},
width=1800,
height=960,
boxmode='group',
font=dict(
family="Courier New, monospace",
size=20,
color="lightslategrey"
)
)

將資料內容設定好之後,便可以將繪圖產出了,如程式碼11所示:

程式碼11:

# 另存html檔
py.plot(fig, filename='多因子變異數分析', auto_open=True)
# 另存png檔
fig.write_image("C:/Users/user/Desktop/多因子變異數分析.png")

產出(如圖3所示):

圖 3 廣告效益交叉比較表

從圖3中可以看到在不同廣告及地區的情況下,平均消費支出的分布,橫軸為不同的地區,縱軸為平均消費金額高低,而線條根據不同的廣告種類,而使用不同的顏色。

雖然在單因子變異數分析的單元中,最終呈現結果看起來被廣告2吸引來的平均消費金額是最低的,可是在加入了地區以後可以發現,原先看似最應該屏棄的廣告2,在北部的所帶來的平均消費金額卻最大,因此也呼應了在該文章中所提到不可任意捨棄廣告2,否則可能會意外損失潛在客群的原因。

透過ANOVA,可幫助企業有效地了解不同要素之間是否有交互作用。除了在本文的案例以外,可以應用的範圍不勝枚舉,例如不同的包裝及定價所帶來的銷售量、不同的薪資制度及福利所帶來的員工滿意度等,若是能善用ANOVA,它將會是您作為分析上的一大幫手!

若喜歡我的文章,請繼續為我拍手,給我動力~

完整程式碼:https://reurl.cc/R1W0Gn

作者:徐子皓(臺灣行銷研究特邀作者)、鍾皓軒(臺灣行銷研究有限公司創辦人)

— — — — — — — — — — — —

往後的文章都會持續在行銷資料科學粉絲專頁上發表喔,喜歡我們就趕緊追蹤吧!

同時再請大家多多follow我們的FB粉絲專頁,我們會在粉專上即時公布最新資訊,讓您重要消息不漏接!

FB粉絲專頁:行銷資料科學

官網:臺灣行銷研究

歡迎加入我們的Telegram獲取即時訊息!https://t.me/marketingdatascience
歡迎加入我們的Line@獲取即時訊息!https://line.me/R/ti/p/%40cde8265r

--

--