0 前言
Hi,大家好,這里是丹成學(xué)長,今天做一個電商銷售預(yù)測分析,這只是一個demo,嘗試對電影數(shù)據(jù)進行分析,并可視化系統(tǒng)
?? 這兩年開始畢業(yè)設(shè)計和畢業(yè)答辯的要求和難度不斷提升,傳統(tǒng)的畢設(shè)題目缺少創(chuàng)新和亮點,往往達不到畢業(yè)答辯的要求,這兩年不斷有學(xué)弟學(xué)妹告訴學(xué)長自己做的項目系統(tǒng)達不到老師的要求。
為了大家能夠順利以及最少的精力通過畢設(shè),學(xué)長分享優(yōu)質(zhì)畢業(yè)設(shè)計項目,今天要分享的是
?? 大數(shù)據(jù)用戶畫像分析系統(tǒng)
??學(xué)長這里給一個題目綜合評分(每項滿分5分)
- 難度系數(shù):3分
- 工作量:3分
- 創(chuàng)新點:4分
項目獲?。?/strong>文章來源:http://www.zghlxwxcb.cn/news/detail-816176.html
https://gitee.com/sinonfin/algorithm-sharing文章來源地址http://www.zghlxwxcb.cn/news/detail-816176.html
實現(xiàn)效果
畢業(yè)設(shè)計 大數(shù)據(jù)用戶行為分析
https://www.bilibili.com/video/BV1Hc41187N3
2 用戶畫像分析概述
用戶畫像是指根據(jù)用戶的屬性、用戶偏好、生活習(xí)慣、用戶行為等信息而抽象出來的標(biāo)簽化用戶模型。通俗說就是給用戶打標(biāo)簽,而標(biāo)簽是通過對用戶信息分析而來的高度精煉的特征標(biāo)識。通過打標(biāo)簽可以利用一些高度概括、容易理解的特征來描述用戶,可以讓人更容易理解用戶,并且可以方便計算機處理。
標(biāo)簽化就是數(shù)據(jù)的抽象能力
- 互聯(lián)網(wǎng)下半場精細化運營將是長久的主題
- 用戶是根本,也是數(shù)據(jù)分析的出發(fā)點
2.1 用戶畫像構(gòu)建的相關(guān)技術(shù)
我們對構(gòu)建用戶畫像的方法進行總結(jié)歸納,發(fā)現(xiàn)用戶畫像的構(gòu)建一般可以分為目標(biāo)分析、體系構(gòu)建、畫像建立三步。
畫像構(gòu)建中用到的技術(shù)有數(shù)據(jù)統(tǒng)計、機器學(xué)習(xí)和自然語言處理技術(shù)(NLP)等,下如圖所示。具體的畫像構(gòu)建方法學(xué)長會在后面的部分詳細介紹。
按照數(shù)據(jù)流處理階段劃分用戶畫像建模的過程,分為三個層,每一層次,都需要打上不同的標(biāo)簽。
- 數(shù)據(jù)層:用戶消費行為的標(biāo)簽。打上事實標(biāo)簽,作為數(shù)據(jù)客觀的記錄
- 算法層:透過行為算出的用戶建模。打上模型標(biāo)簽,作為用戶畫像的分類
- 業(yè)務(wù)層:指的是獲客、粘客、留客的手段。打上預(yù)測標(biāo)簽,作為業(yè)務(wù)關(guān)聯(lián)的結(jié)果
2.2 標(biāo)簽體系
目前主流的標(biāo)簽體系都是層次化的,如下圖所示。首先標(biāo)簽分為幾個大類,每個大類下進行逐層細分。在構(gòu)建標(biāo)簽時,我們只需要構(gòu)建最下層的標(biāo)簽,就能夠映射到上面兩級標(biāo)簽。
上層標(biāo)簽都是抽象的標(biāo)簽集合,一般沒有實用意義,只有統(tǒng)計意義。例如我們可以統(tǒng)計有人口屬性標(biāo)簽的用戶比例,但用戶有人口屬性標(biāo)簽本身對廣告投放沒有任何意義。
2.3 標(biāo)簽優(yōu)先級
構(gòu)建的優(yōu)先級需要綜合考慮業(yè)務(wù)需求、構(gòu)建難易程度等,業(yè)務(wù)需求各有不同,這里介紹的優(yōu)先級排序方法主要依據(jù)構(gòu)建的難易程度和各類標(biāo)簽的依存關(guān)系,優(yōu)先級如下圖所示:
我們把標(biāo)簽分為三類,這三類標(biāo)簽有較大的差異,構(gòu)建時用到的技術(shù)差別也很大。第一類是人口屬性,這一類標(biāo)簽比較穩(wěn)定,一旦建立很長一段時間基本不用更新,標(biāo)簽體系也比較固定;第二類是興趣屬性,這類標(biāo)簽隨時間變化很快,標(biāo)簽有很強的時效性,標(biāo)簽體系也不固定;第三類是地理屬性,這一類標(biāo)簽的時效性跨度很大,如GPS軌跡標(biāo)簽需要做到實時更新,而常住地標(biāo)簽一般可以幾個月不用更新,挖掘的方法和前面兩類也大有不同,如圖所示:
3 實站 - 百貨商場用戶畫像描述與價值分析
3.1 數(shù)據(jù)格式
3.2 數(shù)據(jù)預(yù)處理
部分代碼
# 作者:丹成學(xué)長 Q746876041
import matplotlib
import warnings
import re
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
from sklearn.preprocessing import StandardScaler, MinMaxScaler
%matplotlib inline
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
matplotlib.rcParams.update({'font.size' : 16})
plt.style.use('ggplot')
warnings.filterwarnings('ignore')
df_cum = pd.read_excel('./cumcm2018c1.xlsx')
df_cum
# 先來對會員信息表進行分析
print('會員信息表一共有{}行記錄,{}列字段'.format(df_cum.shape[0], df_cum.shape[1]))
print('數(shù)據(jù)缺失的情況為:\n{}'.format(df_cum.isnull().mean()))
print('會員卡號(不重復(fù))有{}條記錄'.format(len(df_cum['會員卡號'].unique())))
# 會員信息表去重
df_cum.drop_duplicates(subset = '會員卡號', inplace = True)
print('會員卡號(去重)有{}條記錄'.format(len(df_cum['會員卡號'].unique())))
# 去除登記時間的缺失值,不能直接dropna,因為我們需要保留一定的數(shù)據(jù)集進行后續(xù)的LRFM建模操作
df_cum.dropna(subset = ['登記時間'], inplace = True)
print('df_cum(去重和去缺失)有{}條記錄'.format(df_cum.shape[0]))
# 性別上缺失的比例較少,所以下面采用眾數(shù)填充的方法
df_cum['性別'].fillna(df_cum['性別'].mode().values[0], inplace = True)
df_cum.info()
# 由于出生日期這一列的缺失值過多,且存在較多的異常值,不能貿(mào)然刪除
# 故下面另建一個數(shù)據(jù)集L來保存“出生日期”和“性別”信息,方便下面對會員的性別和年齡信息進行統(tǒng)計
L = pd.DataFrame(df_cum.loc[df_cum['出生日期'].notnull(), ['出生日期', '性別']])
L['年齡'] = L['出生日期'].astype(str).apply(lambda x: x[:3] + '0')
L.drop('出生日期', axis = 1, inplace = True)
L['年齡'].value_counts()
...(略)....
3.3 會員年齡構(gòu)成
# 使用上述預(yù)處理后的數(shù)據(jù)集L,包含兩個字段,分別是“年齡”和“性別”,先畫出年齡的條形圖
fig, axs = plt.subplots(1, 2, figsize = (16, 7), dpi = 100)
# 繪制條形圖
ax = sns.countplot(x = '年齡', data = L, ax = axs[0])
# 設(shè)置數(shù)字標(biāo)簽
for p in ax.patches:
height = p.get_height()
ax.text(x = p.get_x() + (p.get_width() / 2), y = height + 500, s = '{:.0f}'.format(height), ha = 'center')
axs[0].set_title('會員的出生年代')
# 繪制餅圖
axs[1].pie(sex_sort, labels = sex_sort.index, wedgeprops = {'width': 0.4}, counterclock = False, autopct = '%.2f%%', pctdistance = 0.8)
axs[1].set_title('會員的男女比例')
plt.savefig('./會員出生年代及男女比例情況.png')
# 繪制各個年齡段的餅圖
plt.figure(figsize = (8, 6), dpi = 100)
plt.pie(res.values, labels = ['中年', '青年', '老年'], autopct = '%.2f%%', pctdistance = 0.8,
counterclock = False, wedgeprops = {'width': 0.4})
plt.title('會員的年齡分布')
plt.savefig('./會員的年齡分布.png')
3.4 訂單占比 消費畫像
# 由于相同的單據(jù)號可能不是同一筆消費,以“消費產(chǎn)生的時間”為分組依據(jù),我們可以知道有多少個不同的消費時間,即消費的訂單數(shù)
fig, axs = plt.subplots(1, 2, figsize = (12, 7), dpi = 100)
axs[0].pie([len(df1.loc[df1['會員'] == 1, '消費產(chǎn)生的時間'].unique()), len(df1.loc[df1['會員'] == 0, '消費產(chǎn)生的時間'].unique())],
labels = ['會員', '非會員'], wedgeprops = {'width': 0.4}, counterclock = False, autopct = '%.2f%%', pctdistance = 0.8)
axs[0].set_title('總訂單占比')
axs[1].pie([df1.loc[df1['會員'] == 1, '消費金額'].sum(), df1.loc[df1['會員'] == 0, '消費金額'].sum()],
labels = ['會員', '非會員'], wedgeprops = {'width': 0.4}, counterclock = False, autopct = '%.2f%%', pctdistance = 0.8)
axs[1].set_title('總消費金額占比')
plt.savefig('./總訂單和總消費占比情況.png')
消費偏好:
我覺得會稍微偏向與消費的頻次,相當(dāng)于消費的訂單數(shù),因為每筆消費訂單其中所包含的消費商品和金額都是不太一樣的,有的訂單所消費的商品很少,但金額卻很大,有的消費的商品很多,但金額卻特別少。如果單純以總金額來衡量的話,會員下次消費時間可能會很長,消費頻次估計也會相對變小(因為這次所購買的商品已經(jīng)足夠用了)。所以我會偏向于認為一個用戶消費頻次(訂單數(shù))越多,就越能帶來更多的價值,從另一方面上來講,用戶也不可能一直都是消費低端產(chǎn)品,消費頻次越多用戶的粘性也會相對比較大
3.5 季度偏好畫像
# 前提假設(shè):2015-2018年之間,消費者偏好在時間上不會發(fā)生太大的變化(均值),消費偏好——>以不同時間的訂單數(shù)來衡量
quarters_list, quarters_order = orders(df_vip, '季度', 3)
days_list, days_order = orders(df_vip, '天', 36)
time_list = [quarters_list, days_list]
order_list = [quarters_order, days_order]
maxindex_list = [quarters_order.index(max(quarters_order)), days_order.index(max(days_order))]
fig, axs = plt.subplots(1, 2, figsize = (18, 7), dpi = 100)
colors = np.random.choice(['r', 'g', 'b', 'orange', 'y'], replace = False, size = len(axs))
titles = ['季度的均值消費偏好', '天數(shù)的均值消費偏好']
labels = ['季度', '天數(shù)']
for i in range(len(axs)):
ax = axs[i]
ax.plot(time_list[i], order_list[i], linestyle = '-.', c = colors[i], marker = 'o', alpha = 0.85)
ax.axvline(x = time_list[i][maxindex_list[i]], linestyle = '--', c = 'k', alpha = 0.8)
ax.set_title(titles[i])
ax.set_xlabel(labels[i])
ax.set_ylabel('均值消費訂單數(shù)')
print(f'{titles[i]}最優(yōu)的時間為: {time_list[i][maxindex_list[i]]}\t 對應(yīng)的均值消費訂單數(shù)為: {order_list[i][maxindex_list[i]]}')
plt.savefig('./季度和天數(shù)的均值消費偏好情況.png')
# 自定義函數(shù)來繪制不同年份之間的的季度或天數(shù)的消費訂單差異
def plot_qd(df, label_y, label_m, nrow, ncol):
"""
df: 為DataFrame的數(shù)據(jù)集
label_y: 為年份的字段標(biāo)簽
label_m: 為標(biāo)簽的一個列表
n_row: 圖的行數(shù)
n_col: 圖的列數(shù)
"""
# 必須去掉最后一年的數(shù)據(jù),只能對2015-2017之間的數(shù)據(jù)進行分析
y_list = np.sort(df[label_y].unique().tolist())[:-1]
colors = np.random.choice(['r', 'g', 'b', 'orange', 'y', 'k', 'c', 'm'], replace = False, size = len(y_list))
markers = ['o', '^', 'v']
plt.figure(figsize = (8, 6), dpi = 100)
fig, axs = plt.subplots(nrow, ncol, figsize = (16, 7), dpi = 100)
for k in range(len(label_m)):
m_list = np.sort(df[label_m[k]].unique().tolist())
for i in range(len(y_list)):
order_m = []
index1 = df[label_y] == y_list[i]
for j in range(len(m_list)):
index2 = df[label_m[k]] == m_list[j]
order_m.append(len(df.loc[index1 & index2, '消費產(chǎn)生的時間'].unique()))
axs[k].plot(m_list, order_m, linestyle ='-.', c = colors[i], alpha = 0.8, marker = markers[i], label = y_list[i], markersize = 4)
axs[k].set_xlabel(f'{label_m[k]}')
axs[k].set_ylabel('消費訂單數(shù)')
axs[k].set_title(f'2015-2018年會員的{label_m[k]}消費訂單差異')
axs[k].legend()
plt.savefig(f'./2015-2018年會員的{"和".join(label_m)}消費訂單差異.png')
# 自定義函數(shù)來繪制不同年份之間的月份消費訂單差異
def plot_ym(df, label_y, label_m):
"""
df: 為DataFrame的數(shù)據(jù)集
label_y: 為年份的字段標(biāo)簽
label_m: 為月份的字段標(biāo)簽
"""
# 必須去掉最后一年的數(shù)據(jù),只能對2015-2017之間的數(shù)據(jù)進行分析
y_list = np.sort(df[label_y].unique().tolist())[:-1]
m_list = np.sort(df[label_m].unique().tolist())
colors = np.random.choice(['r', 'g', 'b', 'orange', 'y'], replace = False, size = len(y_list))
markers = ['o', '^', 'v']
fig, axs = plt.subplots(1, 2, figsize = (18, 8), dpi = 100)
for i in range(len(y_list)):
order_m = []
money_m = []
index1 = df[label_y] == y_list[i]
for j in range(len(m_list)):
index2 = df[label_m] == m_list[j]
order_m.append(len(df.loc[index1 & index2, '消費產(chǎn)生的時間'].unique()))
money_m.append(df.loc[index1 & index2, '消費金額'].sum())
axs[0].plot(m_list, order_m, linestyle ='-.', c = colors[i], alpha = 0.8, marker = markers[i], label = y_list[i])
axs[1].plot(m_list, money_m, linestyle ='-.', c = colors[i], alpha = 0.8, marker = markers[i], label = y_list[i])
axs[0].set_xlabel('月份')
axs[0].set_ylabel('消費訂單數(shù)')
axs[0].set_title('2015-2018年會員的消費訂單差異')
axs[1].set_xlabel('月份')
axs[1].set_ylabel('消費金額總數(shù)')
axs[1].set_title('2015-2018年會員的消費金額差異')
axs[0].legend()
axs[1].legend()
plt.savefig('./2015-2018年會員的消費訂單和金額差異.png')
maxindex = order_nums.index(max(order_nums))
plt.figure(figsize = (8, 6), dpi = 100)
plt.plot(x_list, order_nums, linestyle = '-.', marker = 'o', c = 'm', alpha = 0.8)
plt.xlabel('小時')
plt.ylabel('消費訂單')
plt.axvline(x = x_list[maxindex], linestyle = '--', c = 'r', alpha = 0.6)
plt.title('2015-2018年各段小時的銷售訂單數(shù)')
plt.savefig('./2015-2018年各段小時的銷售訂單數(shù).png')
3.6 會員用戶畫像與特征
3.6.1 構(gòu)建會員用戶業(yè)務(wù)特征標(biāo)簽
# 取DataFrame之后轉(zhuǎn)置取values得到一個列表,再繪制對應(yīng)的詞云,可以自定義一個繪制詞云的函數(shù),輸入?yún)?shù)為df和會員卡號
"""
L: 入會程度(新用戶、中等用戶、老用戶)
R: 最近購買的時間(月)
F: 消費頻數(shù)(低頻、中頻、高頻)
M: 消費總金額(高消費、中消費、低消費)
P: 積分(高、中、低)
S: 消費時間偏好(凌晨、上午、中午、下午、晚上)
X:性別
"""
# 開始對數(shù)據(jù)進行分組
"""
L(入會程度):3個月以下為新用戶,4-12個月為中等用戶,13個月以上為老用戶
R(最近購買的時間)
F(消費頻次):次數(shù)20次以上的為高頻消費,6-19次為中頻消費,5次以下為低頻消費
M(消費金額):10萬以上為高等消費,1萬-10萬為中等消費,1萬以下為低等消費
P(消費積分):10萬以上為高等積分用戶,1萬-10萬為中等積分用戶,1萬以下為低等積分用戶
"""
df_profile = pd.DataFrame()
df_profile['會員卡號'] = df['id']
df_profile['性別'] = df['X']
df_profile['消費偏好'] = df['S'].apply(lambda x: '您喜歡在' + str(x) + '時間進行消費')
df_profile['入會程度'] = df['L'].apply(lambda x: '老用戶' if int(x) >= 13 else '中等用戶' if int(x) >= 4 else '新用戶')
df_profile['最近購買的時間'] = df['R'].apply(lambda x: '您最近' + str(int(x) * 30) + '天前進行過一次購物')
df_profile['消費頻次'] = df['F'].apply(lambda x: '高頻消費' if x >= 20 else '中頻消費' if x >= 6 else '低頻消費')
df_profile['消費金額'] = df['M'].apply(lambda x: '高等消費用戶' if int(x) >= 1e+05 else '中等消費用戶' if int(x) >= 1e+04 else '低等消費用戶')
df_profile['消費積分'] = df['P'].apply(lambda x: '高等積分用戶' if int(x) >= 1e+05 else '中等積分用戶' if int(x) >= 1e+04 else '低等積分用戶')
df_profile
3.6.2 會員用戶詞云分析
# 開始繪制用戶詞云,封裝成一個函數(shù)來直接顯示詞云
def wc_plot(df, id_label = None):
"""
df: 為DataFrame的數(shù)據(jù)集
id_label: 為輸入用戶的會員卡號,默認為隨機取一個會員進行展示
"""
myfont = 'C:/Windows/Fonts/simkai.ttf'
if id_label == None:
id_label = df.loc[np.random.choice(range(df.shape[0])), '會員卡號']
text = df[df['會員卡號'] == id_label].T.iloc[:, 0].values.tolist()
plt.figure(dpi = 100)
wc = WordCloud(font_path = myfont, background_color = 'white', width = 500, height = 400).generate_from_text(' '.join(text))
plt.imshow(wc)
plt.axis('off')
plt.savefig(f'./會員卡號為{id_label}的用戶畫像.png')
plt.show()
4 最后
項目獲?。?/strong>
https://gitee.com/sinonfin/algorithm-sharing
到了這里,關(guān)于畢設(shè)項目 大數(shù)據(jù)用戶畫像分析系統(tǒng)(源碼分享)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!