資料介紹
本案例的業務場景:
假如你們公司投放廣告的渠道很多,每個渠道的客戶性質也可能不同,比如在優酷影片投廣告和今日頭條投放廣告,效果可能會有差異。現在需要對廣告效果分析實現有針對性的廣告效果測量和最佳化工作。
資料13個維度介紹
1、渠道代號:渠道唯一標識
2、日均UV:每天的獨立訪問量
3、平均註冊率=日均註冊使用者數/平均每日訪問量
4、平均搜尋量:每個訪問的搜尋量
5、訪問深度:總頁面瀏覽量/平均每天的訪問量
6、平均停留時長=總停留時長/平均每天的訪問量
7、訂單轉化率=總訂單數量/平均每天的訪客量
8、投放時間:每個廣告在外投放的天數
9、素材型別:‘jpg’ ‘swf’ ‘gif’ ‘sp’
10、廣告型別:banner、tips、不確定、橫幅、暫停
11、合作方式:‘roi’ ‘cpc’ ‘cpm’ ‘cpd’
12、廣告尺寸:‘14040’ ‘308388’ ‘450300’ ‘60090’ ‘480360’ ‘960126’ ‘900120’
‘390270’
13、廣告賣點:打折、滿減、滿贈、秒殺、直降、滿返
匯入庫,匯入資料
import
pandas
as
pd
import
numpy
as
np
import
matplotlib
as
mpl
import
matplotlib。pyplot
as
plt
from
sklearn。preprocessing
import
MinMaxScaler
,
OneHotEncoder
#標準差標準化,獨熱編碼
from
sklearn。metrics
import
silhouette_score
# 匯入輪廓係數指標
from
sklearn。cluster
import
KMeans
# KMeans模組
%
matplotlib
inline
## 設定屬性防止中文亂碼
mpl
。
rcParams
[
‘font。sans-serif’
]
=
[
u
‘SimHei’
]
mpl
。
rcParams
[
‘axes。unicode_minus’
]
=
False
f
=
open
(
‘E://Python練手//一些資料//ad_performance。csv’
,
encoding
=
‘utf-8’
)
ad_data
=
pd
。
read_csv
(
f
)
。
iloc
[:,
1
:]
ad_data
。
head
()
資料審查
檢視基本狀態
ad_data
。
head
()
ad_data
。
info
()
#列印資料型別
RangeIndex: 889 entries, 0 to 888
Data columns (total 13 columns):
渠道代號 889 non-null object
日均UV 889 non-null float64
平均註冊率 889 non-null float64
平均搜尋量 889 non-null float64
訪問深度 889 non-null float64
平均停留時間 887 non-null float64
訂單轉化率 889 non-null float64
投放總時間 889 non-null int64
素材型別 889 non-null object
廣告型別 889 non-null object
合作方式 889 non-null object
廣告尺寸 889 non-null object
廣告賣點 889 non-null object
dtypes: float64(6), int64(1), object(6)
memory usage: 90。4+ KB
ad_data
。
describe
()
。
round
(
2
)
。
T
#列印原資料基本描述資訊
上面程式碼,分別展示前五條資料、所有特徵的資料型別、以及數值型特徵的五值分佈
——————————————————————————————————————
檢視缺失值情況:
# 缺失值審查
ad_data
。
isnull
()
。
any
()
#檢視每一列缺失情況
渠道代號 False
日均UV False
平均註冊率 False
平均搜尋量 False
訪問深度 False
平均停留時間 True
訂單轉化率 False
投放總時間 False
素材型別 False
廣告型別 False
合作方式 False
廣告尺寸 False
廣告賣點 False
dtype: bool
ad_data
。
isnull
()
。
sum
()
。
sort_values
()
# 檢視具有缺失值的行總記錄數
渠道代號 0
日均UV 0
平均註冊率 0
平均搜尋量 0
訪問深度 0
訂單轉化率 0
投放總時間 0
素材型別 0
廣告型別 0
合作方式 0
廣告尺寸 0
廣告賣點 0
平均停留時間 2
dtype: int64
——————————————————————————————————————
變數之間的相關性分析:
# 相關性分析
ad_data
。
corr
()
。
round
(
2
)
# 列印原始資料相關性資訊
# 相關性視覺化展示
import
seaborn
as
sns
corr
=
ad_data
。
corr
()
。
round
(
2
)
sns
。
heatmap
(
corr
,
cmap
=
‘Reds’
,
annot
=
True
)
<
matplotlib
。
axes
。
_subplots
。
AxesSubplot
at
0x2935f4014e0
>
可以看到,“訪問深度”和“平均停留時間”相關性比較高,相關性高說明兩個變數在建立模型的時候,作用是一樣或者效果是一樣的,可以考慮組合或者刪除其一。
資料處理
刪除平均平均停留時間列
ad_data_new
=
ad_data
。
drop
([
‘平均停留時間’
],
axis
=
1
)
ad_data_new
。
head
()
類別變數的獨熱編碼:
cols
=
ad_data_new
。
columns
。
values
。
tolist
()[
-
5
:]
for
x
in
cols
:
data
=
ad_data_new
[
x
]
。
unique
()
(
“變數【{0}】的取值有:
\n
{1}”
。
format
(
x
,
data
))
(
“-·”
*
20
)
變數【素材型別】的取值有:
[‘jpg’ ‘swf’ ‘gif’ ‘sp’]
-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·
變數【廣告型別】的取值有:
[‘banner’ ‘tips’ ‘不確定’ ‘橫幅’ ‘暫停’]
-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·
變數【合作方式】的取值有:
[‘roi’ ‘cpc’ ‘cpm’ ‘cpd’]
-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·
變數【廣告尺寸】的取值有:
[‘140*40’ ‘308*388’ ‘450*300’ ‘600*90’ ‘480*360’ ‘960*126’ ‘900*120’
‘390*270’]
-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·
變數【廣告賣點】的取值有:
[‘打折’ ‘滿減’ ‘滿贈’ ‘秒殺’ ‘直降’ ‘滿返’]
-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·
字串分類獨熱編碼處理
from
sklearn。preprocessing
import
LabelEncoder
,
OneHotEncoder
labelencoder
=
LabelEncoder
()
ad_data_cols
=
ad_data_new
[
cols
]
for
i
in
cols
:
ad_data_cols
[
i
]
=
labelencoder
。
fit_transform
(
ad_data_new
[
i
])
(
“labelencoder:”
)
(
ad_data_cols
。
head
())
labelencoder:
素材型別 廣告型別 合作方式 廣告尺寸 廣告賣點
0 1 0 3 0 0
1 1 0 0 0 1
2 1 0 0 0 1
3 1 0 0 0 1
4 1 0 0 0 1
onehotencoder
=
OneHotEncoder
()
enc_matrix
=
onehotencoder
。
fit_transform
(
ad_data_cols
)
。
toarray
()
(
enc_matrix
[:
2
])
[[0。 1。 0。 0。 1。 0。 0。 0。 0。 0。 0。 0。 1。 1。 0。 0。 0。 0。 0。 0。 0。 1。 0。 0。
0。 0。 0。]
[0。 1。 0。 0。 1。 0。 0。 0。 0。 1。 0。 0。 0。 1。 0。 0。 0。 0。 0。 0。 0。 0。 1。 0。
0。 0。 0。]]
資料標準化
sacle_matrix
=
ad_data_new
。
iloc
[:,
1
:
7
]
# 獲得要轉換的矩陣
model_scaler
=
MinMaxScaler
()
# 建立MinMaxScaler模型物件
data_scaled
=
model_scaler
。
fit_transform
(
sacle_matrix
)
# MinMaxScaler標準化處理
(
data_scaled
。
round
(
2
))
[[0。 0。18 0。02 0。01 0。12 0。66]
[0。01 0。1 0。03 0。01 0。01 0。62]
[0。 0。06 0。05 0。01 0。01 0。1 ]
。。。
[0。01 0。01 0。 0。 0。 0。72]
[0。05 0。 0。 0。 0。 0。31]
[0。 0。 0。 0。53 0。 0。62]]
資料處理完,我們將獨熱編碼的資料和標準化轉化後的資料合併:
# 合併所有維度
X
=
np
。
hstack
((
data_scaled
,
enc_matrix
))
建立模型
# 透過平均輪廓係數檢驗得到最佳KMEANS劇烈模型
score_list
=
list
()
# 用來儲存每個K下模型的平局輪廓係數
silhouette_int
=
-
1
# 初始化的平均輪廓係數閥值
for
n_clusters
in
range
(
2
,
7
):
# 遍歷從2到5幾個有限組
model_kmeans
=
KMeans
(
n_clusters
=
n_clusters
)
# 建立聚類模型物件
labels_tmp
=
model_kmeans
。
fit_predict
(
X
)
# 訓練聚類模型
silhouette_tmp
=
silhouette_score
(
X
,
labels_tmp
)
# 得到每個K下的平均輪廓係數
if
silhouette_tmp
>
silhouette_int
:
# 如果平均輪廓係數更高
best_k
=
n_clusters
# 儲存K將最好的K儲存下來
silhouette_int
=
silhouette_tmp
# 儲存平均輪廓得分
best_kmeans
=
model_kmeans
# 儲存模型例項物件
cluster_labels_k
=
labels_tmp
# 儲存聚類標籤
score_list
。
append
([
n_clusters
,
silhouette_tmp
])
# 將每次K及其得分追加到列表
(
‘{:*^60}’
。
format
(
‘K值對應的輪廓係數:’
))
(
np
。
array
(
score_list
))
# 列印輸出所有K下的詳細得分
(
‘最優的K值是:{0}
\n
對應的輪廓係數是:{1}’
。
format
(
best_k
,
silhouette_int
))
*************************K值對應的輪廓係數:*************************
[[2。 0。38655493]
[3。 0。45757883]
[4。 0。50209812]
[5。 0。4800359 ]
[6。 0。47761127]]
最優的K值是:4
對應的輪廓係數是:0。5020981194788054
總體思想(評價指標)還是怎麼聚才能使得簇內距離足夠小,簇與簇之間平均距離足夠大來評判。
聚類結果特徵分析與展示
透過上面模型,我們其實給每個觀測(樣本)打了個標籤clusters,即他屬於4類中的哪一類:
# 將原始資料與聚類標籤整合
cluster_labels
=
pd
。
DataFrame
(
cluster_labels_k
,
columns
=
[
‘clusters’
])
# 獲得訓練集下的標籤資訊
merge_data
=
pd
。
concat
((
ad_data_new
,
cluster_labels
),
axis
=
1
)
# 將原始處理過的資料跟聚類標籤整合
merge_data
。
head
()
每個類別下的樣本數量和佔比情況
clustering_count
=
pd
。
DataFrame
(
merge_data
[
‘渠道代號’
]
。
groupby
(
merge_data
[
‘clusters’
])
。
count
())
。
T
。
rename
({
‘渠道代號’
:
‘counts’
})
# 計算每個聚類類別的樣本量
clustering_ratio
=
(
clustering_count
/
len
(
merge_data
))
。
round
(
2
)
。
rename
({
‘counts’
:
‘percentage’
})
# 計算每個聚類類別的樣本量佔比
(
clustering_count
)
(
clustering_ratio
)
clusters 0 1 2 3
counts 313 349 154 73
clusters 0 1 2 3
percentage 0。35 0。39 0。17 0。08
每個類別內部最顯著的特徵:
# 計算各個聚類類別內部最顯著特徵值
cluster_features
=
[]
# 空列表,用於儲存最終合併後的所有特徵資訊
for
line
in
range
(
best_k
):
# 讀取每個類索引
label_data
=
merge_data
[
merge_data
[
‘clusters’
]
==
line
]
# 獲得特定類的資料
part1_data
=
label_data
。
iloc
[:,
1
:
7
]
# 獲得數值型資料特徵
part1_desc
=
part1_data
。
describe
()
。
round
(
3
)
# 得到數值型特徵的描述性統計資訊
merge_data1
=
part1_desc
。
iloc
[
2
,
:]
# 得到數值型特徵的均值
part2_data
=
label_data
。
iloc
[:,
7
:
-
1
]
# 獲得字串型資料特徵
part2_desc
=
part2_data
。
describe
(
include
=
‘all’
)
# 獲得字串型資料特徵的描述性統計資訊
merge_data2
=
part2_desc
。
iloc
[
2
,
:]
# 獲得字串型資料特徵的最頻繁值
merge_line
=
pd
。
concat
((
merge_data1
,
merge_data2
),
axis
=
0
)
# 將數值型和字串型典型特徵沿行合併
cluster_features
。
append
(
merge_line
)
# 將每個類別下的資料特徵追加到列表
# 輸出完整的類別特徵資訊
cluster_pd
=
pd
。
DataFrame
(
cluster_features
)
。
T
# 將列表轉化為矩陣
all_cluster_set
=
pd
。
concat
((
clustering_count
,
clustering_ratio
,
cluster_pd
),
axis
=
0
)
# 將每個聚類類別的所有資訊合併
all_cluster_set
圖形化輸出
# 獲取要展示的資料
num_sets
=
cluster_pd
。
T
。
iloc
[:,
:
6
]
。
astype
(
np
。
float64
)
# 獲得標準化後的資料
num_sets_max_min
=
model_scaler
。
fit_transform
(
num_sets
)
(
num_sets
)
(
‘-’
*
60
)
(
num_sets_max_min
)
日均UV 平均註冊率 平均搜尋量 訪問深度 訂單轉化率 投放總時間
0 1390。013 0。003 0。152 1。168 0。017 8。199
1 933。015 0。003 0。064 5。916 0。006 8。770
2 2717。419 0。005 0。051 0。947 0。007 8。529
3 1904。371 0。003 0。106 0。943 0。009 8。217
——————————————————————————————
[[2。56106801e-01 0。00000000e+00 1。00000000e+00 4。52443193e-02
1。00000000e+00 0。00000000e+00]
[0。00000000e+00 0。00000000e+00 1。28712871e-01 1。00000000e+00
0。00000000e+00 1。00000000e+00]
[1。00000000e+00 1。00000000e+00 0。00000000e+00 8。04343455e-04
9。09090909e-02 5。77933450e-01]
[5。44358789e-01 0。00000000e+00 5。44554455e-01 0。00000000e+00
2。72727273e-01 3。15236427e-02]]
# 畫圖
fig
=
plt
。
figure
(
figsize
=
(
6
,
6
))
# 建立畫布
ax
=
fig
。
add_subplot
(
111
,
polar
=
True
)
# 增加子網格,注意polar引數
labels
=
np
。
array
(
merge_data1
。
index
)
# 設定要展示的資料標籤
cor_list
=
[
‘g’
,
‘r’
,
‘y’
,
‘b’
]
# 定義不同類別的顏色
angles
=
np
。
linspace
(
0
,
2
*
np
。
pi
,
len
(
labels
),
endpoint
=
False
)
# 計算各個區間的角度
angles
=
np
。
concatenate
((
angles
,
[
angles
[
0
]]))
# 建立相同首尾欄位以便於閉合
# 畫雷達圖
for
i
in
range
(
len
(
num_sets
)):
# 迴圈每個類別
data_tmp
=
num_sets_max_min
[
i
,
:]
# 獲得對應類資料
data
=
np
。
concatenate
((
data_tmp
,
[
data_tmp
[
0
]]))
# 建立相同首尾欄位以便於閉合
ax
。
plot
(
angles
,
data
,
‘o-’
,
c
=
cor_list
[
i
],
label
=
“第
%d
類渠道”
%
(
i
+
1
))
# 畫線
ax
。
fill
(
angles
,
data
,
alpha
=
2。5
)
# 設定影象顯示格式
ax
。
set_thetagrids
(
angles
*
180
/
np
。
pi
,
labels
,
fontproperties
=
“SimHei”
)
# 設定極座標軸
ax
。
set_title
(
“各聚類類別顯著特徵對比”
,
fontproperties
=
“SimHei”
)
# 設定標題放置
ax
。
set_rlim
(
-
0。2
,
1。2
)
# 設定座標軸尺度範圍
plt
。
legend
(
loc
=
“upper right”
,
bbox_to_anchor
=
(
1。2
,
1。0
))
# 設定圖例位置
<
matplotlib
。
legend
。
Legend
at
0x2935f4dcb00
>
資料結論
從案例結果來看,所有的渠道被分為4各類別,每個類別的樣本量分別為:154、349 、313、73,對應占比分別為:17%、39%、35%、8%。
透過雷達圖可以清楚的知道:
類別1(索引為2類的渠道)
這類廣告媒體除了訪問深度和投放時間較高,其他屬性較低,因此這類廣告媒體效果質量較差,並且佔到39%,因此這類是主體渠道之一。
業務部門要考慮他的實際投放價值。
類別2(索引為0類的渠道)
這類廣告媒體除了訪問深度略差,在平均搜尋量、日均UV、訂單轉化率等廣告效果指標上表現良好,是一類綜合效果較好的渠道。
但是日均UV是短板,較低。無法給企業帶來大量的流量以及新使用者,這類廣告的特質適合使用者轉化,尤其是有關訂單的轉化提升。
類別3(索引為1類的渠道)
這類廣告媒體的顯著特徵是日均UV和註冊率較高,其“引流”和“拉新”效果好,可以在廣告媒體中定位為引流角色。
符合“廣而告之”的訴求,適合“拉新”使用。
類別4(索引為3類的渠道)
這類渠道各方面特徵都不明顯,各個流量質量和流量數量的指標均處於“中等”層次。不突出但是均衡,考慮在各場景下可以考慮在這個渠道投放廣告。