畢業(yè)設(shè)計(jì) 大數(shù)據(jù)抖音短視頻數(shù)據(jù)分析與可視化
0 前言
?? 這兩年開始畢業(yè)設(shè)計(jì)和畢業(yè)答辯的要求和難度不斷提升,傳統(tǒng)的畢設(shè)題目缺少創(chuàng)新和亮點(diǎn),往往達(dá)不到畢業(yè)答辯的要求,這兩年不斷有學(xué)弟學(xué)妹告訴學(xué)長自己做的項(xiàng)目系統(tǒng)達(dá)不到老師的要求。
為了大家能夠順利以及最少的精力通過畢設(shè),學(xué)長分享優(yōu)質(zhì)畢業(yè)設(shè)計(jì)項(xiàng)目,今天要分享的是
?? ?基于大數(shù)據(jù)的抖音短視頻數(shù)據(jù)分析與可視化
??學(xué)長這里給一個題目綜合評分(每項(xiàng)滿分5分)
工作量:3分
創(chuàng)新點(diǎn):3分
畢設(shè)幫助,選題指導(dǎo),技術(shù)解答,歡迎打擾,見B站個人主頁
https://space.bilibili.com/33886978
1 課題背景
本項(xiàng)目是大數(shù)據(jù)---基于抖音用戶數(shù)據(jù)集的可視化分析。抖音作為當(dāng)下非常熱門的短視頻軟件,其背后的數(shù)據(jù)有極高的探索價(jià)值。本項(xiàng)目根據(jù)1737312條用戶行為數(shù)據(jù),利用python工具進(jìn)行由淺入深的內(nèi)容分析,目的是挖掘其中各類信息,更好地進(jìn)行內(nèi)容優(yōu)化、產(chǎn)品運(yùn)營。
2 數(shù)據(jù)清洗
數(shù)據(jù)信息查看
簡單看一下前5行數(shù)據(jù),確定需要進(jìn)一步預(yù)處理的內(nèi)容:數(shù)據(jù)去重、刪除沒有意義的第一列,部分列格式轉(zhuǎn)換、異常值檢測。
# 讀取數(shù)據(jù)
df = pd.read_csv('data.csv')
df.head()

df.info()

數(shù)據(jù)去重
無重復(fù)數(shù)據(jù)
print('去重前:',df.shape[0],'行數(shù)據(jù)')
print('去重后:',df.drop_duplicates().shape[0],'行數(shù)據(jù)')
缺失值查看
print(np.sum(df.isnull()))

變量類型轉(zhuǎn)換
real_time 和 date 轉(zhuǎn)為時(shí)間變量,id、城市編碼轉(zhuǎn)為字符串,并把小數(shù)點(diǎn)去掉
df['date'] = df['date'].astype('datetime64[ns]')
df['real_time'] = df['real_time'].astype('datetime64[ns]')
df['uid'] = df['uid'].astype('str')
df['user_city'] = df['user_city'].astype('str')
df['user_city'] = df['user_city'].apply(lambda x:x[:-2])
df['item_id'] = df['item_id'].astype('str')
df['author_id'] = df['author_id'].astype('str')
df['item_city'] = df['item_city'].astype('str')
df['item_city'] = df['item_city'].apply(lambda x:x[:-2])
df['music_id'] = df['music_id'].astype('str')
df['music_id'] = df['music_id'].apply(lambda x:x[:-2])
df.info()

3 數(shù)據(jù)可視化
基本信息的可視化,面向用戶、創(chuàng)作者以及內(nèi)容這三個維度進(jìn)行,構(gòu)建成分畫像,便于更好地針對用戶、創(chuàng)作者進(jìn)行策略投放、內(nèi)容推廣與營銷。
地區(qū)-用戶
user_city_count = user_info.groupby(['user_city']).count().sort_values(by=['uid'],ascending=False)
x1 = list(user_city_count.index)
y1 = user_city_count['uid'].tolist()
len(y1)
不同地區(qū)用戶數(shù)量分布圖
#柱形圖代碼
chart = Bar()
chart.add_xaxis(x1)
chart.add_yaxis('地區(qū)使用人數(shù)', y1, color='#F6325A',
? ? ? ? ? ? ? ? ? ? itemstyle_opts={'barBorderRadius':[60, 60, 20, 20]},
? ? ? ? ? ? ? ? ? ? ?label_opts=opts.LabelOpts(position='top'))
chart.set_global_opts(datazoom_opts=opts.DataZoomOpts(
? ?range_start=0,range_end=5,orient='horizontal',type_='slider',is_zoom_lock=False, ?pos_left='1%' ),
? ?visualmap_opts=opts.VisualMapOpts(is_show = False,type_='opacity',range_opacity=[0.2, 1]),
? ? ? ? ? ? ? ? ? ? title_opts=opts.TitleOpts(title="不同地區(qū)用戶數(shù)量分布圖",pos_left='40%'),
? ? ? ? ? ? ? ? ? ? legend_opts=opts.LegendOpts(pos_right='10%',pos_top='2%'))
chart.render_notebook()

覆蓋到了387個城市,其中編號為99的城市用戶比較多超過2000人,6、129、109、31這幾個城市的使用人數(shù)也超過了1000。
可以關(guān)注用戶較多城市的特點(diǎn),對產(chǎn)品受眾有進(jìn)一步的把握。
用戶較少的城市可以視作流量洼地,考慮進(jìn)行地推/用戶-用戶的推廣,增加地區(qū)使用人數(shù)。
觀看時(shí)間
h_num = round((df.groupby(['H']).count()['uid']/10000),1).to_list()
h = list(df.groupby(['H']).count().index)
不同時(shí)間觀看數(shù)量分布圖
chart = Line()
chart.add_xaxis(h)
chart.add_yaxis('觀看數(shù)/(萬)',h_num, areastyle_opts=opts.AreaStyleOpts(color = '#1AF5EF',opacity=0.3),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?itemstyle_opts=opts.ItemStyleOpts(color='black'),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?label_opts=opts.LabelOpts(font_size=12))
chart.set_global_opts(legend_opts=opts.LegendOpts(pos_right='10%',pos_top='2%'),
? ? ? ? ? ? ? ? ? ? title_opts=opts.TitleOpts(title="不時(shí)間觀看數(shù)量分布圖",pos_left='40%'),)
chart.render_notebook()
去掉時(shí)差后

根據(jù)不同時(shí)間的觀看視頻數(shù)量來看,11-18,20-21,尤其是13-16是用戶使用的高峰期
在用戶高瀏覽的時(shí)段進(jìn)行廣告的投放,曝光量更高
在高峰段進(jìn)行優(yōu)質(zhì)內(nèi)容的推薦,效果會更好
分界線
點(diǎn)贊/完播率分布圖
left = df.groupby(['H']).sum()[['finish','like']]
right = df.groupby(['H']).count()['uid']
per = pd.concat([left,right],axis=1)
per['finish_radio'] = round(per['finish']*100/per['uid'],2)
per['like_radio'] = round(per['like']*100/per['uid'],2)
x = list(df.groupby(['H']).count().index)
y1 = per['finish_radio'].to_list()
y2 = per['like_radio'].to_list()#建立一個基礎(chǔ)的圖形
chart1 = Line()
chart1.add_xaxis(x)
chart1.add_yaxis('完播率/%',y1,is_smooth=True,label_opts=opts.LabelOpts(is_show=False),is_symbol_show = False,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?linestyle_opts=opts.LineStyleOpts(color='#F6325A',opacity=.7,curve=0,width=2,type_= 'solid' ))
chart1.set_global_opts(yaxis_opts = ?opts.AxisOpts(min_=25,max_=45))
chart1.extend_axis(yaxis=opts.AxisOpts(min_=0.4,max_=3))
#疊加折線圖
chart2 = Line() ?
chart2.add_xaxis(x)
chart2.add_yaxis('點(diǎn)贊率/%',y2,yaxis_index=1,is_smooth=True,label_opts=opts.LabelOpts(is_show=False),is_symbol_show = False,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?linestyle_opts=opts.LineStyleOpts(color='#1AF5EF',opacity=.7,curve=0,width=2,type_= 'solid' ))
chart1.overlap(chart2)
chart1.set_global_opts(legend_opts=opts.LegendOpts(pos_right='10%',pos_top='2%'),
? ? ? ? ? ? ? ? ? ? title_opts=opts.TitleOpts(title="點(diǎn)贊/完播率分布圖",pos_left='40%'),)
chart1.render_notebook()

關(guān)注到點(diǎn)贊率和完播率,這兩個與用戶粘性、創(chuàng)作者收益有一定關(guān)系的指標(biāo)??梢钥吹?5點(diǎn)是兩個指標(biāo)的小高峰,2、4、20、23完播較高,8、13、18、20點(diǎn)贊率較高。但結(jié)合觀看數(shù)量與時(shí)間段的分布圖,大致猜測15點(diǎn)深度用戶較多。
關(guān)注深度用戶特點(diǎn),思考如何增加普通用戶的完播、點(diǎn)贊
每周觀看
df['weekday'] = df['date'].dt.weekday
week = df.groupby(['weekday']).count()['uid'].to_list()
df_pair = [['周一', week[0]], ['周二', week[1]], ['周三', week[2]], ['周四', week[3]], ['周五', week[4]], ['周六', week[5]], ['周日', week[6]]]chart = Pie()
chart.add('', df_pair,radius=['40%', '70%'],rosetype='radius',center=['45%', '50%'],label_opts=opts.LabelOpts(is_show=True,formatter = ':{c}次'))
chart.set_global_opts(visualmap_opts=[opts.VisualMapOpts(min_=200000,max_=300000,type_='color', range_color=['#1AF5EF', '#F6325A', '#000000'],is_show=True,pos_top='65%')],
? ? ? ? ? ? ? ? ? ? ?legend_opts=opts.LegendOpts(pos_right='10%',pos_top='2%',orient='vertical'),
? ? ? ? ? ? ? ? ? ? title_opts=opts.TitleOpts(title="一周內(nèi)播放分布圖",pos_left='35%'),)
chart.render_notebook()

在統(tǒng)計(jì)的時(shí)間內(nèi)周一到周三觀看人數(shù)較多,但總體觀看次數(shù)基本在20-30w之間。
創(chuàng)作者選擇在周一-三這幾天分布可能會收獲更多的觀看數(shù)量
觀看路徑
df.groupby(['channel']).count()['uid']

觀看途徑主要以1為主,初步猜測為App。3途徑也有部分用戶使用,可能為瀏覽器。
考慮拓寬各個觀看渠道,增加總體播放量和產(chǎn)品使用度
非主渠道觀看,制定策略提升轉(zhuǎn)化,將流量引入主渠道
針對主要渠道內(nèi)容進(jìn)行商業(yè)化策略投放,效率更高
發(fā)布地點(diǎn)
author_info = df.drop_duplicates(['author_id','item_city'])[['author_id','item_city']]
author_info.info()
author_city_count = author_info.groupby(['item_city']).count().sort_values(by=['author_id'],ascending=False)
x1 = list(author_city_count.index)
y1 = author_city_count['author_id'].tolist()df.drop_duplicates(['author_id']).shape[0]
不同城市創(chuàng)作者分布圖
chart = Bar()
chart.add_xaxis(x1)
chart.add_yaxis('地區(qū)創(chuàng)作者人數(shù)', y1, color='#F6325A',
? ? ? ? ? ? ? ? ? ? itemstyle_opts={'barBorderRadius':[60, 60, 20, 20]})
chart.set_global_opts(datazoom_opts=opts.DataZoomOpts(
? ?range_start=0,range_end=5,orient='horizontal',type_='slider',is_zoom_lock=False, ?pos_left='1%' ),
? ?visualmap_opts=opts.VisualMapOpts(is_show = False,type_='opacity',range_opacity=[0.2, 1]),
? ? ? ? ? ? ? ? ? ? legend_opts=opts.LegendOpts(pos_right='10%',pos_top='2%'),
? ? ? ? ? ? ? ? ? ? title_opts=opts.TitleOpts(title="不同城市創(chuàng)作者分布圖",pos_left='40%'))
chart.render_notebook()

觀看用戶地區(qū)分布和創(chuàng)作者分布其實(shí)存在不對等的情況。4地區(qū)創(chuàng)作者最多,超5k人,33、42、10地區(qū)創(chuàng)作者也較多。
創(chuàng)作者與地區(qū)的聯(lián)系也值得關(guān)注,尤其是創(chuàng)作內(nèi)容如果和當(dāng)?shù)仫L(fēng)俗環(huán)境人文有關(guān)
相鄰近地區(qū)的優(yōu)質(zhì)的創(chuàng)作者之間互動,可以更好的引流
視頻時(shí)長
time = df.drop_duplicates(['item_id'])[['item_id','duration_time']]
time = time.groupby(['duration_time']).count()
x1 = list(time.index)
y1 = time['item_id'].tolist()
不同時(shí)長作品分布圖
chart = Bar()
chart.add_xaxis(x1)
chart.add_yaxis('視頻時(shí)長對應(yīng)視頻數(shù)', y1, color='#1AF5EF',
? ? ? ? ? ? ? ? ? ? itemstyle_opts={'barBorderRadius':[60, 60, 20, 20]},
? ? ? ? ? ? ? label_opts=opts.LabelOpts(font_size=12, ?color='black'))
chart.set_global_opts(datazoom_opts=opts.DataZoomOpts(
? ?range_start=0,range_end=50,orient='horizontal',type_='slider'),
? ?visualmap_opts=opts.VisualMapOpts(max_=100000,min_=200,is_show = False,type_='opacity',range_opacity=[0.4, 1]),
? ? ? ? ? ? ? ? ? ? legend_opts=opts.LegendOpts(pos_right='10%',pos_top='2%'),
? ? ? ? ? ? ? ? ? ? title_opts=opts.TitleOpts(title="不同時(shí)長作品分布圖",pos_left='40%'))
chart.render_notebook()

視頻時(shí)長主要集中在9-10秒,符合抖音“短”視頻的特點(diǎn)。
官方提供9/10秒專用剪視頻模板,提高創(chuàng)作效率
創(chuàng)作者關(guān)注創(chuàng)意濃縮和內(nèi)容提煉
視頻分布在這兩個時(shí)間點(diǎn)的爆發(fā)也能側(cè)面反映用戶刷視頻的行為特征
整體點(diǎn)贊、完播
like_per = 100*np.sum(df['like'])/len(df['like'])
finish_per = 100*np.sum(df['finish'])/len(df['finish'])gauge = Gauge()
gauge.add("",[("視頻互動率", like_per),['完播率',finish_per]],detail_label_opts=opts.LabelOpts(is_show=False,font_size=18),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?axisline_opts=opts.AxisLineOpts(linestyle_opts=opts.LineStyleOpts(
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?color=[(0.3, "#1AF5EF"), (0.7, "#F6325A"), (1, "#000000")],width=20)))
gauge.render_notebook()

內(nèi)容整體完播率非常接近40%,點(diǎn)贊率在1%左右
用戶更多是“刷”視頻,挖掘吸引力和作品連貫性,能更好留住用戶
點(diǎn)贊功能挖掘不夠,可嘗試進(jìn)行ABtest,對點(diǎn)贊按鈕增加動畫,測試是否會提升點(diǎn)贊率
4 進(jìn)階分析
相關(guān)性分析
df_cor = df[['finish','like','duration_time','H']] # 只選取部分
cor_table = df_cor.corr(method='spearman')
cor_array = np.array(cor_table)
cor_name = list(cor_table.columns)
value = [[i, j, cor_array[i,j]] for i in [3,2,1,0] for j in [0,1,2,3]] heat = HeatMap()
heat.add_xaxis(cor_name)
heat.add_yaxis("",cor_name,value,label_opts=opts.LabelOpts(is_show=True, position="inside"))
heat.set_global_opts(visualmap_opts=opts.VisualMapOpts(is_show=False, max_=0.08, range_color=["#1AF5EF", "#F6325A", "#000000"]))
heat.render_notebook()

因?yàn)樽兞糠沁B續(xù),采取spearman相關(guān)系數(shù),制作相關(guān)性熱力圖。由于數(shù)據(jù)量比較大的緣故,幾個數(shù)量性變量之間的相關(guān)性都比較小,其中看到finish和點(diǎn)贊之間的相關(guān)系數(shù)稍微大一些,可以一致反映用戶對該視頻的偏好。
留存率
pv/uv
temp = df['date'].to_list()
puv = df.groupby(['date']).agg({'uid':'nunique','item_id':'count'})
uv = puv['uid'].to_list()
pv = puv['item_id'].to_list()
time = puv.index.to_list()chart1 = Line()
chart1.add_xaxis(time)
chart1.add_yaxis('uv',uv,is_smooth=True,label_opts=opts.LabelOpts(is_show=False),is_symbol_show = False,
? ? ? ? ? ? ? ?linestyle_opts=opts.LineStyleOpts(color='#1AF5EF',opacity=.7,curve=0,width=2,type_= 'solid' ))
chart1.add_yaxis('pv',pv,is_smooth=True,label_opts=opts.LabelOpts(is_show=False),is_symbol_show = False,
? ? ? ? ? ? ? ?linestyle_opts=opts.LineStyleOpts(color='#F6325A',opacity=.7,curve=0,width=2,type_= 'solid' ))
chart1.render_notebook()

在2019.10.18進(jìn)入用戶使用高峰階段,目標(biāo)用戶單人每天瀏覽多個視頻。
關(guān)注高峰時(shí)間段,是否是當(dāng)下推薦算法起作用了
7/10 留存率
lc = []
for i in range(len(time)-7):
? ?bef = set(list(df[df['date']==time[i]]['uid']))
? ?aft = set(list(df[df['date']==time[i+7]]['uid']))
? ?stay = bef&aft
? ?per = round(100*len(stay)/len(bef),2)
? ?lc.append(per)
? ?
lc1 = []
for i in range(len(time)-1):
? ?bef = set(list(df[df['date']==time[i]]['uid']))
? ?aft = set(list(df[df['date']==time[i+1]]['uid']))
? ?stay = bef&aft
? ?per = round(100*len(stay)/len(bef),2)
? ?lc1.append(per)x7 = time[0:-7]
chart1 = Line()
chart1.add_xaxis(x7)
chart1.add_yaxis('七日留存率/%',lc,is_smooth=True,label_opts=opts.LabelOpts(is_show=False),is_symbol_show = False,
? ? ? ? ? ? ? ?linestyle_opts=opts.LineStyleOpts(color='#F6325A',opacity=.7,curve=0,width=2,type_= 'solid' ))
chart1.set_global_opts(legend_opts=opts.LegendOpts(pos_right='10%',pos_top='2%'),
? ? ? ? ? ? ? ? ? ? title_opts=opts.TitleOpts(title="用戶留存率分布圖",pos_left='40%'),)
chart1.render_notebook()

用戶留存率保持在40%+,且沒有跌破30%,說明獲取到的數(shù)據(jù)中忠實(shí)用戶較多。
存在一定可能性是因?yàn)閿?shù)據(jù)只爬取了特定用戶群體的行為數(shù)據(jù),結(jié)合創(chuàng)作者數(shù)量>用戶數(shù)量可得到驗(yàn)證
但一定程度可以反映軟件留存這塊做的不錯
5 深度分析
客戶價(jià)值判斷
通過已觀看數(shù)、完播率、點(diǎn)贊率進(jìn)行用戶聚類,價(jià)值判斷
df1 = df.groupby(['uid']).agg({'item_id':'count','like':'sum','finish':'sum'})
df1['like_per'] = df1['like']/df1['item_id']
df1['finish_per'] = df1['finish']/df1['item_id']
ndf1 = np.array(df1[['item_id','like_per','finish_per']])#.shapekmeans_per_k = [KMeans(n_clusters=k).fit(ndf1) for k in range(1,8)]
inertias = [model.inertia_ for model in kmeans_per_k]
chart = Line(init_opts=opts.InitOpts(width='560px',height='300px'))
chart.add_xaxis(range(1,8))
chart.add_yaxis("",inertias,label_opts=opts.LabelOpts(is_show=False),
? ? ? ? ? ? ? ?linestyle_opts=opts.LineStyleOpts(color='#F6325A',opacity=.7,curve=0,width=3,type_= 'solid' ))
chart.render_notebook()

n_cluster = 4
cluster = KMeans(n_clusters=n_cluster,random_state=0).fit(ndf1)
y_pre = cluster.labels_ # 查看聚好的類
from sklearn.metrics import silhouette_score
from sklearn.metrics import silhouette_samples
silhouette_score(ndf1,y_pre) n_cluster = 3
cluster = KMeans(n_clusters=n_cluster,random_state=0).fit(ndf1)
y_pre = cluster.labels_ # 查看聚好的類
from sklearn.metrics import silhouette_score
from sklearn.metrics import silhouette_samples
silhouette_score(ndf1,y_pre)
比較三類、四類的輪廓系數(shù),確定聚為3類
c_ = [[],[],[]]
c_[0] = [87.998,9.1615,39.92]
c_[1] = [13.292,12.077,50.012]
c_[2] = [275.011,8.125,28.751]bar = Bar(init_opts=opts.InitOpts(theme='macarons',width='1000px',height='400px')) # 添加分類(x軸)的數(shù)據(jù)
bar.add_xaxis(['播放數(shù)','點(diǎn)贊率(千分之)','完播率(百分之)'])
bar.add_yaxis('0', [round(i,2) for i in c_[0]], stack='stack0')
bar.add_yaxis('1',[round(i,2) for i in c_[1]], stack='stack1')
bar.add_yaxis('2',[round(i,2) for i in c_[2]], stack='stack2')
bar.render_notebook()

可以大致對三類的內(nèi)容做一個描述。
紫色 - 觀看數(shù)量較少,但點(diǎn)贊完播率都非常高的:對內(nèi)容觀看有耐心,愿意產(chǎn)生額外性行為。因此通過觀看興趣內(nèi)容打散、可以刺激用戶觀看更多視頻。e.g.多推薦有懸念、連續(xù)性的短視頻
綠色 - 觀看數(shù)量適中,點(diǎn)贊率、完播率有所下滑,對這類用戶的策略可以中和先后兩種。
藍(lán)色 - 觀看數(shù)量非常多,點(diǎn)贊、完播率教室,這類用戶更多會關(guān)注到視頻前半段的內(nèi)容,興趣點(diǎn)可通過停留時(shí)間進(jìn)行判斷,但使用時(shí)間相對較長,反映產(chǎn)品依賴性,一定程度上來說算是核心用戶。e.g.利用停留時(shí)間判斷喜好,優(yōu)化推薦算法,重點(diǎn)推薦前半段內(nèi)容吸引力大的。
畢設(shè)幫助,選題指導(dǎo),技術(shù)解答,歡迎打擾,見B站個人主頁
https://space.bilibili.com/33886978