在现实生活中,有时候我们可能得到一大堆无标签文本,这时候可能需要对文本进行聚类挖掘,找出热点问题是什么。
文本聚类
第一步:数据读取
import pandas as pd
import re
import jieba
csv='95598处理后.csv'
file_txt=pd.read_csv(csv, header=0,encoding='gbk')#
file_txt=file_txt.dropna()#删除空值[4229 rows x 2 columns]
print(file_txt.head())
其他格式数据读取方法
现实生活中 文本数据有可能不是表格,是txt文件。
txt读取方法链接:
python读取txt文件(多种方法)
这里简单演示下读取一个文件夹下的所有txt文件数据.
原始文件夹 一张图两个txt
import os
import re
#首先定义规则,如我们需要把所有的txt文件
pattern=re.compile(r'.+\.txt')
for root ,dirs,files in os.walk(r'C:\Users\Shineion\Desktop\新建文件夹'):
for name in files:
file_path=os.path.join(root,name)#包含路径的文件
matching=pattern.search(file_path)#匹配txt
if matching:
command_line =file_path.replace('/', '\\') #\\ 变 \
print(command_line)
f = open(command_line,encoding='utf')
data = f.readlines() # 直接将文件中按行读到list里,效果与方法2一样
f.close() # 关
print(data) # 返回list
简单演示啦下,读取出来的数据有换行符\n。需要的时候正则化处理就可以啦。
如果是Word文字读取,参考链接
python自动化办公:word篇。职场高手不是梦。
第二步:预处理函数
去除数字字母 和停用词
停用词链接:nlp 中文停用词数据集
# 定义删除除字母,数字,汉字以外的所有符号的函数
def remove_punctuation(line):
line = str(line)
if line.strip() == '':
return ''
rule = re.compile(u"[^a-zA-Z0-9\u4E00-\u9FA5]")
line = rule.sub('', line)
return line
#停用词
def stopwordslist(filepath):
stopwords = [line.strip() for line in open(filepath, 'r', encoding='gbk').readlines()]
return stopwords
第三步:数据预处理实现
其中clean_review代表去除数字字母后的文本,cut_review代表去除停用词后的文本
# 加载停用词
stopwords = stopwordslist("停用词.txt")
#去除标点符号
file_txt['clean_review']=file_txt['ACCEPT_CONTENT'].apply(remove_punctuation)
#去除停用词
file_txt['cut_review']=file_txt['clean_review'].apply(lambda x:" ".join([w for w in list(jieba.cut(x)) if w not in stopwords]))
print(file_txt.head())
第四步:tf-idf
from sklearn.feature_extraction.text import CountVectorizer#词袋
from sklearn.feature_extraction.text import TfidfTransformer#tfidf
#词袋计数
count_vect = CountVectorizer()
X = count_vect.fit_transform(file_txt['cut_review'])
#tf-idf
tfidf_transformer = TfidfTransformer()
X_tfidf = tfidf_transformer.fit_transform(X)
print(X_tfidf)
第五步:手肘法选择聚类中心数
①手肘法
手肘法的核心指标是SSE(sum of the squared errors,误差平方和),
其中,Ci是第i个簇,p是Ci中的样本点,mi是Ci的质心(Ci中所有样本的均值),SSE是所有样本的聚类误差,代表了聚类效果的好坏。
手肘法的核心思想是:随着聚类数k的增大,样本划分会更加精细,每个簇的聚合程度会逐渐提高,那么误差平方和SSE自然会逐渐变小。并且,当k小于真实聚类数时,由于k的增大会大幅增加每个簇的聚合程度,故SSE的下降幅度会很大,而当k到达真实聚类数时,再增加k所得到的聚合程度回报会迅速变小,所以SSE的下降幅度会骤减,然后随着k值的继续增大而趋于平缓,也就是说SSE和k的关系图是一个手肘的形状,而这个肘部对应的k值就是数据的真实聚类数。当然,这也是该方法被称为手肘法的原因。
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
# '利用SSE选择k'
SSE = [] # 存放每次结果的误差平方和
for k in range(1, 9):
estimator = KMeans(n_clusters=k) # 构造聚类器
estimator.fit(X_tfidf)
SSE.append(estimator.inertia_)
X = range(1, 9)
plt.xlabel('k')
plt.ylabel('SSE')
plt.plot(X, SSE, 'o-')
plt.show()
从图中看到,肘部并未明显出现,这时候我们应该扩大更大数值如范围1到10。 其实我们也隐约的知道 肘部数据为7或者8.我们就取7吧。
第六步:聚类实现
# K均值聚类
model_kmeans = KMeans(n_clusters=7,random_state=1) # 创建聚类模型对象
model_kmeans.fit(X_tfidf) # 训练模型
# 聚类结果
cluster_labels = model_kmeans.labels_ # 聚类标签结果
print(cluster_labels)
第七步:结果拼接汇总
将聚类得到的标签和原始数据进行拼接.
我这里选择的是将分词结果和标签进行拼接。
可以拼接更多的数据,如再加上原文。
#结果拼接
labels=pd.DataFrame(cluster_labels,columns=['标签'])
shuju=pd.concat([file_txt['cut_review'],labels],axis=1)
print(shuju)
第八步:统计每类词汇
cat_desc = dict()
biaoqian_values=[0,1,2,3,4,5,6]#聚类标签
for i in biaoqian_values:
text = shuju.loc[shuju['标签'] == i, 'cut_review']
text = (' '.join(map(str, text))).split(' ')
cat_desc[i] = text
print(cat_desc[2])#打印2类词汇
第九步:绘制高频词词云
#词云图
#查看词云
from collections import Counter
from wordcloud import WordCloud
def generate_wordcloud(tup):
wordcloud = WordCloud(background_color='white',
font_path='simhei.ttf',
max_words=50, max_font_size=40,
random_state=42
).generate(str(tup))
return wordcloud
fig, axes = plt.subplots(4, 2, figsize=(30, 38))
k = 0
for i in range(4):
for j in range(2):
most10 = Counter(cat_desc[k]).most_common(10)#10个高频词
ax = axes[i, j]
ax.imshow(generate_wordcloud(most10), interpolation="bilinear")
ax.axis('off')
ax.set_title("{} Top 10".format(k), fontsize=30)
if k<6:
k += 1
plt.show()
因为只有7个类别,我的画布是(4,2)所以最后一幅图画2次
if k<6:
k += 1
本文给出的原始文本数据 都属于电力工单,所以高频词云图你看起来决定很相似。如果给出的原始文本数据多种多样,饮食,体育,那结果显示就不一样的。
第10步:统计各类词频
如果你不想结果以词云图显示,想以文本格式显示。
from collections import Counter
for i in range(7):
most10 = Counter(cat_desc[i]).most_common(10)
print('第{0}类前10个高频词'.format(i),most10)
总结
本文给出的文本数据例子可能不是太好。各类之间高度相似。
思路:分词 ,tf-idf ,聚类 ,聚类结果和原始分词拼接,绘制高频词云图,统计各类高频词。
即可得到热点问题是什么。
大家好,我是余登武。电气工程的计算机萌新。写博文不容易。如果你觉得本文对你有用,请点个赞支持下,谢谢。