Python数据分析实战——使用K-means进行知网学者画像分析
文章目录一、数据准备二、数据清洗三、EDA四、共现网络五、K-means聚类六、数据降维,可视化结果一、数据准备这次主要是通过知网获取的学者信息,进行一个学者画像的分析。一共是从知网下载了三份数据。如下图所示。每份数据的格式都是一样的。包含'SrcDatabase-来源库', 'Title-题名', 'Author-作者', 'Organ-单位', 'Source-文献来源', 'Keyword-
文章目录
一、数据准备
这次主要是通过知网获取的学者信息,进行一个学者画像的分析。
一共是从知网下载了三份数据。如下图所示。
每份数据的格式都是一样的。包含'SrcDatabase-来源库', 'Title-题名', 'Author-作者', 'Organ-单位', 'Source-文献来源', 'Keyword-关键词', 'Summary-摘要', 'PubTime-发表时间'
八个字段。
因此我们可以将这三份数据合并到一个DataFrame中,再进行后续的数据清洗。代码如下。
import pandas as pd
import numpy as np
import os
import matplotlib.pyplot as plt
plt.style.use('seaborn')
base='./datasets/'
datasets=os.listdir(base)
print(datasets)
dfs=[]
for dataset in datasets:
df=pd.read_excel(os.path.join(base,dataset),encoding='gbk')
dfs.append(df)
df=pd.concat(dfs)
df.head()
二、数据清洗
1、缺失值处理
观察上述合并后的数据,可以看到第一列数据是不需要的。
其次,部分列的数据存在缺失值,对于存在缺失值的元素,这里直接删除对应行即可。
2、异常值
这里的异常值主要是部列中的值为标题名称。这里做个筛选,同样删除这些数据即可。
三、EDA
数据清洗完毕后接着进行数据探索。可以看到数据集中的各列数据均有挖掘价值。将相关内容可视化化出来。
1、发表文章数量最多的作者
从数据列可以发现,有的文章为多名作者合作完成,因此需要做一个简单的拆分
keywords={}
exponet=[]#每篇文章各个关键词出现次数之和,排序依据
for keys in df['Author-作者']:
key_list=keys.split(';')
for key in key_list:
if key=='':
continue
if key in keywords:
keywords[key]+=1
else:
keywords[key]=1
keywords=dict(sorted(keywords.items(),key=lambda x:x[1],reverse=True)[:10])
plt.title('发表文章最多作者Top10')
plt.bar(keywords.keys(),keywords.values())
plt.xticks(rotation=30)
#排序DataFrame
for keys in df['Author-作者']:
score=0
for key in keys.split(';'):
try:
score+=keywords[key]
except:
pass
exponet.append(score)
df['数量']=exponet
df=df.sort_values(by='数量',ascending=False)
print("根据作着排序结果如下:")
df.head()
2、发表时间统计
这里我们统计每年总共发表的文章数量
dates=pd.to_datetime(df['PubTime-发表时间'])
year_num=dates.map(lambda x:x.year).value_counts()
year_num.index=year_num.index.sort_values(ascending=False)
year_num.plot()
plt.xlabel('年份')
plt.ylabel('文章累计数')
3、发表单位统计
接着统计各个单位发表数量的Top10
organ=df['Organ-单位'].value_counts()
organ[:10].plot(kind='bar',title='单位发表数量top10')
df['数量']=[organ[i] for i in df['Organ-单位'] ]
df=df.sort_values(by='数量',ascending=False)
print("根据单位排序结果如下:")
df.head()
4、文献来源统计
Source=df['Source-文献来源'].value_counts()
Source[:10].plot(kind='bar',title='文献来源数量top10')
df['数量']=[Source[i] for i in df['Source-文献来源'] ]
df=df.sort_values(by='数量',ascending=False)
print("根据单位排序结果如下:")
df.head()
5、关键词统计
关键词统计的方法与1中的作者发表文章数量的统计方法类似。这里我们统计前15个关键词
keywords={}
exponet=[]#每篇文章各个关键词出现次数之和,排序依据
for keys in df['Keyword-关键词']:
key_list=keys.split(';')
for key in key_list:
if key=='':
continue
if key in keywords:
keywords[key]+=1
else:
keywords[key]=1
keywords=dict(sorted(keywords.items(),key=lambda x:x[1],reverse=True)[:10])
plt.title('关键词Top10')
plt.bar(keywords.keys(),keywords.values())
plt.xticks(rotation=30)
#排序DataFrame
for keys in df['Keyword-关键词']:
score=0
for key in keys.split(';'):
try:
score+=keywords[key]
except:
pass
exponet.append(score)
df['数量']=exponet
df=df.sort_values(by='数量',ascending=False)
print("根据关键词排序结果如下:")
df.head()
四、共现网络
构建作者与作者之间的合作网络。那么这个思路主要如下。
首先是将所有作者提取出来,这个在之前数据探索的过程中已经实现。将作者名作为行与列构建一个新的矩阵。
authors=[]
ketwords={}
for keys in df['Author-作者']:
key_list=keys.split(';')
for key in key_list:
if key=='':
continue
if key in keywords:
keywords[key]+=1
else:
keywords[key]=1
if key not in authors:
authors.append(key)
l=len(authors)
arr=np.zeros((l,l))
co_author_arr=pd.DataFrame(arr,index=authors,columns=authors)
co_author_arr.head()
对于上述的Dataframe我们将他当作一个二维数组,那么:
当作者i与作者j在同一条记录出现时,co_author_arr[i][j]+=1
,然后将同一个关系合并co_author_arr[i][j]+=co_author_arr[j][i]
。最后形成我们最终的结果。
如果用Python的基本循环语法去遍历这个数据会是一个很漫长的过程。所以我们通过Pandas内置的迭代对象进行遍历。
leg=len(authors)
count=0
for index,row in co_author_arr.iterrows():
for name in row.index:
if name!=index:
row[name]+=1
row[name]+=co_author_arr.loc[name,index]
count+=1
print('\r{}%'.format(count/leg*100),end='')
co_author_arr.head()
最后结果如下
五、K-means聚类
由于每篇文章都包含多个不同的主题,我们为了能更合理地归类这些文章,可以将这些文章进行聚类。
将所有唯一的关键词作为行,所有文章标题作为列构建一个新的DataFrame,所有元素初始化为0。
如果当前文章包括某个关键词,则将该元素的值置为1。
- 建立聚类表格
keywords=[]
for keys in df['Keyword-关键词']:
key_list=keys.split(';')
for key in key_list:
if key=='':
continue
if key not in keywords:
keywords.append(key)
title=df['Title-题名']
arr=np.zeros((len(title),len(keywords)))
tit_key=pd.DataFrame(arr,index=title,columns=keywords)
tit_key.head()
- 计算结果
df=df.set_index('Title-题名')
for index,row in tit_key.iterrows():
kw=df.loc[index,'Keyword-关键词']
try:
keys=kw.split(';')
for k in keys:
if k in keywords:
row[k]=1
except:
pass
tit_key.head()
- 为了选取最优的簇数,我们通过不同的评估系数(CH指标、轮廓系数指标、SSE簇内误方差指标)进行评估,根据可视化的结果选取最佳的K值
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
from sklearn.metrics import calinski_harabaz_score
#三种评价指标
silhouettteScore = []
CH_score=[]
SSE=[]
for i in range(2,30):
##构建并训练模型
print('\r正在构建模型:{}%'.format((i-1)/28*100),end='')
kmeans = KMeans(n_clusters = i,random_state=123).fit(tit_key)
score = silhouette_score(tit_key,kmeans.labels_)
ch=calinski_harabaz_score(tit_key,kmeans.labels_)
silhouettteScore.append(score)
CH_score.append(ch)
SSE.append(kmeans.inertia_)
def plot_one(scores,title):
plt.figure(figsize=(10,6))
plt.plot(range(2,30),scores,linewidth=1.5, linestyle="-")
plt.title(title)
plot_one(silhouettteScore,'轮廓系数')
plot_one(CH_score,'CH')
plot_one(SSE,'SSE')
通过上图,我们选择K=16作为聚类的簇数
六、数据降维,可视化结果
from sklearn.manifold import TSNE
kmeans=KMeans(n_clusters=16,random_state=123).fit(tit_key) #构建并训练模型
tsne = TSNE(n_components=2,init='random',random_state=177).fit(tit_key)
result=pd.DataFrame(tsne.embedding_) ##将原始数据转换为DataFrame
result['labels'] = kmeans.labels_ ##将聚类结果存储进df数据表
# ## 绘制图形
plt.figure(figsize=(12,10))
for i in range(17):
temp=result[result['labels']==i]
plt.scatter(temp[0],temp[1])
七、数据集+源码获取
关注以下公众号,回复0020
即可获取下载链接
更多推荐
所有评论(0)