大家好,我是小五????
前情回顾:用两种非传统的爬虫,来看看你写的博客各项数据达标了没~
今天就来一波数据分析,走起~
一、数据介绍
数据来源:从首页Python、Java等十个栏目共爬取7868条数据
数据字段:
字段名 | 含义 |
blog_name | 博主名 |
code_time | 码龄 |
blog_num | 博客数 |
view_num | 访问量 |
fans_num | 粉丝数 |
like_num | 点赞数 |
comments_num | 评论数 |
collections_num | 收藏数 |
二、数据预处理
首先,我们来预览下数居
import pandas as pd
df = pd.read_csv('csdn_user.csv',encoding='gb18030')
df.info()
从结果来看,除博客数外,其他均为字符型变量。code_time(码龄)存在一条缺失值,删除即可。
df = df.dropna(how='any',axis=0)
由于不同栏目下会有同一作者发布的博客,所以需要依据博主名进行去重处理
df1 = df.drop_duplicates(subset='blog_name',keep='last',ignore_index=True)
print('重复数据共{}条,现有数据{}条'.format(len(df)-len(df1),len(df1)))
从结果来看,共2680条重复数据,现有5187条博主信息数据。
为后续分析方便,这里将所有的"万+"都转化为对应的数字,如1万+转化为10000(所有的博主的博客数尚未达到一万,故不用转化)。此外,为了解同层次博主排名,加入我自己的博客信息。
variable=['view_num','fans_num','likes_num','collections_num']
for var in variable:
df1[var]=df1[var].map(lambda x:int(x.replace('万+','0000') if '万+' in x else x))
df1 = df1.append([{'blog_name':'皖渝','code_time':'码龄2年','blog_num':43,'view_num':40000,
'fans_num':113,'likes_num':82,'comments_num':99,'collections_num':258}],ignore_index=True)
三、探索数据分析
(1) 各类码龄博主分布及平均水平
def sns_bar(data,column,ylab,title,adjust_num):
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
plt.rcParams['axes.unicode_minus']=False
sns.set(font='kaiti')
index=np.arange(len(data))
plt.figure(figsize=(10,6))
g=sns.barplot(data.index,data[column],
palette='Set3',alpha=0.8)
for name,count in zip(index,data[column]):
g.text(name,count+adjust_num,int(count),
ha='center',va='bottom')
plt.title(title)
plt.ylabel(ylab)
plt.xticks(rotation=90)
plt.show()
bloger_code=df1['code_time'].value_counts().to_frame()
sns_bar(bloger_code,'code_time','人数','CSDN博主码龄分布',2)
、 从上图来看,在本次爬取的样本中,码龄2年的博主最多,共1124人;其次是码龄1年和3年的,总体来看"年轻"的博主占多数呀。此外,码龄超过15年(包括)的共28人,最长竟达到了20年!(respect)
顺便来计算下,各个码龄层次的博主数据的平均分布情况
num_variable=['blog_num','view_num','fans_num','likes_num','comments_num','collections_num']
bloger_data = df1.groupby('code_time')[num_variable].mean()
bloger_data
从上表来看,码龄2年的博主平均发博75篇,平均访问量为47043次,平均粉丝数为92个,平均点赞数为81次,平均评论数为36条,平均收藏数为182条。(哈哈哈,除了发博数和访问量,我都达标了,看来达到平均水平了呀,未来继续努力~)
(2) 构建博主影响力模型
用因子分析法构建影响力模型,如下所示:
其中,score
为单个博主的影响力综合值,λ
为各因子的方差贡献率,F
为各个公共因子
这里使用的则是Python自带因子分析库FactorAnalyzer(默认公共因子的数量为3)
1.变量标准化
from sklearn import preprocessing
num_variable=['blog_num','view_num','fans_num','likes_num','comments_num','collections_num']
df2=pd.concat([df1[['blog_name','code_time']],
pd.DataFrame(preprocessing.scale(df1[num_variable]),columns=num_variable)],axis=1)
2.确定公共因子个数
import numpy.linalg as nlg
C=df2.corr()
eig_value,eig_vector=nlg.eig(C)
eig=pd.DataFrame() #利用变量名和特征值建立一个数据框
eig['names']=df2.columns[2:]#列名
eig['eig_value']=eig_value#特征值
# 确定公共因子个数
for k in range(1,7):
var_cum = eig['eig_value'][:k].sum()/eig['eig_value'].sum()
print('累计方差贡献率为{}'.format(var_cum))
if var_cum>=0.8:
print('确定公共因子数为{}'.format(k))
break
从输出结果来看,当公共因子数为4个时,累计方差率达到82%,即可解释原数据82%的信息。
3.比较旋转前后载荷矩阵
from factor_analyzer import FactorAnalyzer,Rotator
data = df2[num_variable] #提取数值型变量
fa = FactorAnalyzer(4,rotation=None)
fa.fit(data)
print('未旋转前因子载荷矩阵:\n',fa.loadings_)
rotator = Rotator()
print("按正交旋转后的因子载荷矩阵:\n", rotator.fit_transform(fa.loadings_))
不难看出,旋转后载荷矩阵各列中的值差别较大。公共因子F1在评论数上的载荷较大,可命名为互动因子;公共因子F2在博客数上载荷较大,可命名为创作因子;公共因子F3在点赞数和收藏数上有着较大的载荷,可命名为认可因子;公共因子F4在粉丝数上有较大的载荷,可命名人气因子。
4.计算综合得分
fa1 = FactorAnalyzer(4,rotation='varimax') #使用正交旋转
fa1.fit(data)
def score(factors):
return sum(factors*fa1.get_factor_variance()[1])
scores = []
for i in range(len(fa1.transform(data))):
new = score(fa1.transform(data)[i])
scores.append(new)
df2['scores']=scores
#综合影响力前10名博主可视化
outstaning_bloger = df2.sort_values(by='scores',ascending=False)[:10][['blog_name','scores']].set_index('blog_name')
sns_bar(outstaning_bloger,'scores','综合影响力','综合影响力排名前十位10位优质博主',0.02)
排名前三名的是沉默的王二,guolin,敖丙,向大佬们学习!
再来计算下,我的综合影响力在码龄2年的博主中的排名吧~
code_time2_group = df2[df2['code_time']=='码龄2年'].sort_values(by='scores',ascending=False,ignore_index=True)
my_rank = code_time2_group[code_time2_group['blog_name']=='皖渝'].index+1
print('码龄2年的博主共{}人,我的排名为第{}名,比例为{}'.format(len(code_time2_group),my_rank[0],my_rank[0]/len(code_time2_group)))
在码龄2年的博主中,我的排名为149名,挤进了前15%呀~
(3) 探究影响力与码龄的相关关系
在得到所有博主的综合影响力后,我们可以思考一个问题:综合影响力是否和码龄的长短有关呢?
1、从纯数据角看,我们可以计算各类码龄博主的平均影响力,如下图所示:
code_score = df2.groupby('code_time')['scores'].mean().to_frame()
code_score = code_score.sort_values(by='scores',ascending=False)
sns_bar(code_score,'scores','平均影响力','各类码龄博主的平均影响力',0.0005)
从上图来看,明显看出综合影响力较高的博主大多为老博主,而影响力较低的博主大多为新博主。
2、从统计视角看,该问题可转化为不同码龄层次博主的影响力是否有显著性差异。此时,我们尝试使用单因素方差分析,但该方法使用前需要满足两个假定条件:方差齐性和正态性。正态性一般对方差分析结果影响不大,在此忽略。以下,就进行方差齐性的检验。
原假设 :各类码龄博主的影响力方差相等
from scipy import stats
code_time_list = ['码龄'+str(i)+'年' for i in range(19)]+['码龄20年']
total_df=[]
for code_time in code_time_list:
total_df.append(df2[df2['code_time']==code_time]['scores'])
w,p = stats.levene(*total_df)
w,p
结果表示,在0.05显著性水平下,强烈拒绝原假设。故方差齐性的假设不满足,无法使用单因素方差分析进行探究。继而,我们可以转向非参数统计。在Python中Kruskal可以检验多样本均值差异,且无需假定各样本方差相等。
k,p = stats.kruskal(*total_df)
k,p
结果显示,在0.05显著性水平下,强烈拒绝原假设。故我们有充分理由认为不同码龄博主的影响力是具有显著差异的。
以上就是本次分享的全部内容~