羊城地区heyTea部分门店顾客评价数据可视化挖掘分析
羊城地区HeyTea门店顾客评价数据可视化挖掘分析
开题背景
众所周知,HEYTEA,曾名“皇茶”,是一家由深圳美西西餐饮管理有限公司运营的中国连锁茶饮品牌。2012年,喜茶HEYTEA起源于江边里的一条小巷,为了与层出不穷的山寨品牌区分开来,故全面升级为注册品牌喜茶HEYTEA。由聂云宸于2012年创立,总部设在深圳市南山区航天科技广场,旗下拥有茶饮品牌“喜茶”和烘焙品牌“喜茶热麦”。
该公司依赖社交媒体上的口碑营销以减少广告支出。年轻消费者是其主要客户。大多数店面都在一二线城市的繁华购物中心。其知名产品为芝士奶盖。喜茶为芝士现泡茶的原创者。自创立以来,喜茶专注于呈现来自世界各地的优质茶香, 让这茶饮这一古老文化焕发出新的生命力。
在全国各大城市中,如此广为人知的一家奶茶店铺,我们自然会对其在广大消费者眼中的评价感到兴趣,这些评价对于慕名而来的消费者,也有着极高的参考价值。毕竟,一家企业的好和坏,并不能由单一的门店的产品质量来讨论,故而,这里在羊城地域,随机抽样择取了其所有门店中的部分顾客评价,并对其展开分析,希望得出的结论,可以对未来的消费者提供一份有价值的参考。
环境配置
1 !pip install pyLDAvis
1 !pip install wordcloud 2 3 # 读取/预处理数据库 4 5 import pandas as pd 6 7 import numpy as np 8 9 import time 10 11 # 可视化工具 12 13 import matplotlib.pyplot as plt 14 15 import seaborn as sns 16 17 from wordcloud import WordCloud, ImageColorGenerator # 词云可视化 18 19 # 分词工具 20 21 import jieba 22 23 import jieba.posseg as psg 24 25 import re 26 27 # 文本特征提取工具 28 29 from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer, HashingVectorizer 30 31 from sklearn.decomposition import LatentDirichletAllocation 32 33 # LDA主题模型可视化 34 35 import pyLDAvis 36 37 import pyLDAvis.sklearn 38 39 import paddlenlp
数据源文件如下:
数据包括评价文本及评价时间两个字段。
2 数据读取与预处理
2.1数据读取
1 data = pd.read_excel("data/data155443/xicha_meituan_data.xlsx") 2 3 # 词典文件路径 可以分特定词 4 5 dic_file = r"file/dict.txt" 6 7 stop_file = r"file/cn_stopwords.txt"
2.2数据预处理
1 data.info()
1 # 去除无内容的评价
2 data = data.dropna()
4 data.head(5)
2.2.1针对文本数据内容的预处理
1 # 分词函数 2 3 def chinese_word_cut(mytext): 4 5 jieba.load_userdict(dic_file) 6 7 jieba.initialize() 8 9 try: 10 11 stopword_list = open(stop_file,encoding ='utf-8') 12 13 except: 14 15 stopword_list = [] 16 17 print("error in stop_file") 18 19 stop_list = [] 20 21 flag_list = ['n','nz','vn','a','an','ad','i'] 22 23 for line in stopword_list: 24 25 line = re.sub(u'\n|\\r', '', line) 26 27 stop_list.append(line) 28 29 30 31 word_list = [] 32 33 #jieba分词 34 35 seg_list = psg.cut(mytext,use_paddle=True) 36 37 for seg_word in seg_list: 38 39 word = seg_word.word 40 41 find = 0 42 43 if seg_word.flag == 'x': 44 45 find=1 46 47 for stop_word in stop_list: 48 49 if stop_word == word : 50 51 find = 1 52 53 break 54 55 if find == 0 : # and seg_word.flag in flag_list 56 57 word_list.append(word) 58 59 return (" ").join(word_list) 60 61 # 计算分词后文本的词频 62 63 def count_frequencies(word_list): 64 65 freq = dict() 66 67 for sentence in word_list: 68 69 for w in sentence.split(' '): 70 71 if w not in freq.keys(): 72 73 freq[w] = 1 74 75 else: 76 77 freq[w] += 1 78 79 return freq 80 81 data["cutted_comment"] = data.comment.apply(chinese_word_cut)
1 freq = count_frequencies(data["cutted_comment"]) 2 3 freq = sorted(freq.items(),key=lambda x:x[1],reverse=True) 4 5 freq[:15]
1 len(freq)
1 # 去除过短的评论 2 3 t_data = data[data['cutted_comment'].str.len()>5] 4 5 t_data = t_data.reset_index().drop(columns='index')
2.2.2 评价时间字段数据预处理
1 t=time.localtime(1650933910610/1000)
2 time.strftime("%Y-%m-%d %H:%M:%S",t).split(' ')
1 _date=[] 2 3 _date_month=[] 4 5 _date_day=[] 6 7 _time=[] 8 9 _time_hour=[] 10 11 for i in t_data['comment_time']: 12 13 arr=time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(i/1000)).split(' ') 14 15 _date.append(arr[0]) 16 17 _date_month.append(arr[0].split('-')[1]) 18 19 _date_day.append(arr[0].split('-')[2]) 20 21 _time.append(arr[1]) 22 23 _time_hour.append(arr[1].split(':')[0]) 24 25 t_data.insert(2,value=_date_month,column='_date_month') 26 27 t_data.insert(3,value=_date_day,column='_date_day') 28 29 t_data.insert(4,value=_time_hour,column='_time_hour') 30 31 t_data.head(5)
2.2.3 基于paddleNLP.TaskFlow评价情感分析
1 sa = paddlenlp.Taskflow('sentiment_analysis')
1 sentiment_analysis_data = sa(t_data['comment'].to_list()) 2 3 sentiment_analysis_data_df = pd.DataFrame(sentiment_analysis_data) 4 5 sentiment_analysis_data_df.head(5)
1 t_data['label'] = sentiment_analysis_data_df['label'] 2 3 t_data['score'] = sentiment_analysis_data_df['score'] 4 5 # 保存 6 7 t_data.to_excel('file/data.xlsx',index=False,encoding='utf8') 8 9 t_data.head(5)
1 t_data.info()
抽样区域内门店评价数据可视化实现
2.1店内图文及词云可视化显示
1 def plt_imshow(x, ax=None, show=True): 2 3 if ax is None: 4 5 fig, ax = plt.subplots() 6 7 ax.imshow(x) 8 9 ax.axis("off") 10 11 if show: plt.show() 12 13 return ax 14 15 wcd = WordCloud(background_color='white', 16 17 max_words=200, 18 19 font_path = 'file/font/SIMHEI.TTF', 20 21 mode="RGBA", 22 23 max_font_size=180, 24 25 width = 1300, 26 27 height = 800, 28 29 scale=10 30 31 ) 32 33 wcd.generate_from_frequencies(dict(freq)) 34 35 ax=plt_imshow(wcd) 36 37 ax.figure.savefig('file/pic/wordcloud0.png',dpi=1000)
我们可以得知:利用WordCloud库和处理后的评价数据进行词云图制作,得到下图,可以看到“好喝”、“不错”、“味道”等词在评价中经常出现,可以体现出顾客在喜茶门店具有较好的服务感知满意度;
“芝士”、“葡萄”、“芒果”、“草莓”等词也的出现频率也是不低,对此,我们可知:服务产品中水果类饮品较多样顾客对该类商品有较深的印象;
“环境”、“口味”、“味道”、“清爽”等词,则形象生动地表明了顾客对门店服务支持设施和显性服务有一定的关注。
1 plt.figure(figsize=(19,6)) 2 3 ax=sns.countplot( 4 5 t_data['_date_month'], 6 7 saturation =1, 8 9 palette=sns.color_palette(palette='OrRd_d',desat=0.9,n_colors=12), 10 11 ) 12 13 plt.title('Number of monthly reviews of HEYTEA',fontsize=30) 14 15 plt.xlabel('Month',fontsize=30) 16 17 plt.ylabel("Count",fontsize=30) 18 19 plt.savefig('file/pic/每月评价数.png',dpi=1000)
根据这一则数据我们可知:喜茶评价数据大多在上半年3到6月份,下半年评价数据较少。因此,我们可以推断出:春季是奶茶饮品的旺季,而从盛夏至严冬的时段,这一类产品显然不如春季之时受消费者欢迎。
1 plt.figure(figsize=(19,6)) 2 3 ax=sns.countplot( 4 5 t_data['_date_day'], 6 7 saturation =1, 8 9 palette=sns.color_palette(palette='PuBu',desat=1,n_colors=10) 10 11 ) 12 13 plt.title('Number of Daily reviews of HEYTEA',fontsize=30) 14 15 plt.xlabel('Day',fontsize=30) 16 17 plt.ylabel("Count",fontsize=30) 18 19 plt.savefig('file/pic/一个月中每日评价数.png',dpi=1000)
我们进一步对喜茶12个月中每天评价数据进行统计,则可以得到下图。如图所示,在每月12号、18号和29号评价数据较多;在1号、11号和19号较少,对此,相应调整店内原材料以及人员的配比,也会是提高营业效益的一种方式。
1 plt.figure(figsize=(19,6)) 2 3 ax=sns.countplot( 4 5 t_data['_time_hour'], 6 7 saturation=1, 8 9 palette=sns.color_palette(palette='OrRd_d',desat=1) 10 11 ) 12 13 plt.title('Number of Hours reviews of HEYTEA',fontsize=30) 14 15 plt.xlabel('Every hour of the day',fontsize=30) 16 17 plt.ylabel("Count",fontsize=30) 18 19 plt.savefig('file/pic/一个天中24小时评价数.png',dpi=1000)
1 # 消极评论每天各个时段散点图 2 3 plt.figure(figsize=(12,9)) 4 5 sns.swarmplot(y=t_data['_time_hour'],x=t_data['label']) 6 7 plt.title('HEYTEA Distribution of good and bad reviews in various time periods of the day',fontsize=15) 8 9 plt.xlabel('Label',fontsize=20) 10 11 plt.ylabel('per hours of day',fontsize=20)
1 plt.savefig('file/pic/一天内各个时段好差评数据分布.png',dpi=1000) 2 3 # 消极评论每个月散点图 4 5 plt.figure(figsize=(12,9)) 6 7 sns.swarmplot(y=t_data['_date_month'],x=t_data['label'])
1 # 消极评论每个月内散点图 2 3 plt.figure(figsize=(12,9)) 4 5 sns.swarmplot(y=t_data['_date_day'],x=t_data['label'])
1 sns.countplot(t_data['label']) 2 3 plt.title(r"HEYTEA Negative vs. positive reviews",fontsize=15) 4 5 plt.ylabel('Count',fontsize=15) 6 7 plt.xlabel('HEYTEA Comment Label',fontsize=15) 8 9 plt.savefig('file/pic/喜茶评价积极与消极比较.png',dpi=1000)
ax=sns.barplot(
1 y=[len(t_data['comment']),len(t_data['comment'].unique())], 2 3 x=['all_comment','unique_comment'], 4 5 ) 6 7 plt.title('HEYTEA comments''s uniqueness',fontsize=15) 8 9 plt.ylabel('Count',fontsize=15) 10 11 plt.savefig('file/pic/喜茶评价唯一性.png',dpi=1000)
1 ax=sns.barplot( 2 3 y=[len(t_data['comment']),len(t_data['comment'].unique())], 4 5 x=['all_comment','unique_comment'], 6 7 ) 8 9 plt.title('HEYTEA comments''s uniqueness',fontsize=15) 10 11 plt.ylabel('Count',fontsize=15) 12 13 plt.savefig('file/pic/喜茶评价唯一性.png',dpi=1000)
1 print('消极评论占比',sum(t_data['label']=='negative')/len(t_data)) 2 3 # 消极评论词云图 4 5 freq_negative = count_frequencies(t_data[t_data['label']=='negative']['cutted_comment']) 6 7 freq_negative = sorted(freq_negative.items(),key=lambda x:x[1],reverse=True) 8 9 freq_negative[:15]
1 wcd = WordCloud(background_color='white', 2 3 max_words=150, 4 5 font_path = 'file/font/SIMHEI.TTF', 6 7 mode="RGBA", 8 9 max_font_size=160, 10 11 width = 1000, 12 13 height = 500, 14 15 scale=10) 16 17 wcd.generate_from_frequencies(dict(freq_negative[4:])) 18 19 ax=plt_imshow(wcd) 20 21 ax.figure.savefig('file/pic/wordcloud_negative.png',dpi=1000)
挖掘——LDA模型主题
3.1提取文本特征
1 n_features = 1000 #提取1000个特征词语 2 3 cv_vectorizer = CountVectorizer(max_df = 0.90, 4 5 max_features=n_features, 6 7 min_df = 5) 8 9 cv = cv_vectorizer.fit_transform(t_data.cutted_comment) 10 11 # tfidf提取文本特征 12 13 tfidf_vectorizer = TfidfVectorizer(max_df = 0.95, 14 15 max_features=500) 16 17 tfidf = tfidf_vectorizer.fit_transform(t_data.cutted_comment) 18 19 hash_vectorizer = HashingVectorizer() 20 21 hashing = hash_vectorizer.fit_transform(data.cutted_comment)
3.2 LDA困惑度与主题数选择
1 plexs = [] 2 3 n_max_topics = 50 4 5 for i in range(1,n_max_topics): 6 7 print(i,end='..') 8 9 lda = LatentDirichletAllocation(n_components=i, 10 11 doc_topic_prior=1/i, 12 13 topic_word_prior=1/i, 14 15 learning_method='batch') 16 17 lda.fit(cv) 18 19 plexs.append(lda.perplexity(cv))
1 n_t=50#区间最右侧的值。注意:不能大于n_max_topics 2 3 x=list(range(1,n_t)) 4 5 plt.plot(x,plexs[:n_t], linestyle='-.') 6 7 plt.xlabel("number of topics") 8 9 plt.ylabel("perplexity") 10 11 plt.legend(('perplexity_value')) 12 13 plt.title("LDA Model Perplexity Value") 14 15 plt.savefig('file/pic/PerplexityValue.png',dpi=1000) 16 17 plt.show()
3.3 LDA模型训练与模型结果
1 n_topics = 4 2 3 lda = LatentDirichletAllocation(n_components=n_topics,max_iter=100, 4 5 doc_topic_prior=1/n_topics, 6 7 topic_word_prior=0.01, 8 9 learning_method='batch') 10 11 lda.fit(cv)
def print_top_words(model, feature_names, n_top_words):
1 tword = [] 2 3 for topic_idx, topic in enumerate(model.components_): 4 5 print("Topic #%d:" % topic_idx) 6 7 topic_w = " ".join([feature_names[i] for i in topic.argsort()[:-n_top_words - 1:-1]]) 8 9 tword.append(topic_w) 10 11 print(topic_w) 12 13 return tword 14 15 # 输出每个主题及其主题词 16 17 n_top_words = 15 18 19 cv_vectorizer_name = cv_vectorizer.get_feature_names() 20 21 topic_word = print_top_words(lda, cv_vectorizer_name, n_top_words)
1 # LDA模型还可以用于文本分类 2 3 topics=lda.transform(cv) 4 5 topic = [] 6 7 for t in topics: 8 9 topic.append("Topic #"+str(list(t).index(np.max(t)))) 10 11 t_data['概率最大的主题序号']=topic 12 13 t_data['每个主题对应概率']=list(topics) 14 15 t_data.to_excel("data_topic_test0.xlsx",index=False)
3.4 LDA模型结果可视化
1 pyLDAvis.enable_notebook() 2 3 pic = pyLDAvis.sklearn.prepare(lda, cv,cv_vectorizer) 4 5 pyLDAvis.display(pic) 6 7 pyLDAvis.save_html(pic, 'file/pic/lda_pass'+str(n_topics)+'.html') 8 9 pyLDAvis.display(pic) 10 11 #去工作路径下找保存好的html文件
在文件下找到生成的html文件,用浏览器打开可以看到具体结果
运行结果如图所示:
3.5测试调查结果
结合LDA主题挖掘与情感分析统计的结果,可以得出hey Tea在羊城(广州)地区的门店主要的运营问题是排队时间过长的结论,同时可以推断该问题在中午的13点与下午的17点经常频发。
完整代码附上:
1 !pip install pyLDAvis 2 3 !pip install wordcloud 4 5 # 读取/预处理数据库 6 7 import pandas as pd 8 9 import numpy as np 10 11 import time 12 13 # 可视化工具 14 15 import matplotlib.pyplot as plt 16 17 import seaborn as sns 18 19 from wordcloud import WordCloud, ImageColorGenerator # 词云可视化 20 21 # 分词工具 22 23 import jieba 24 25 import jieba.posseg as psg 26 27 import re 28 29 # 文本特征提取工具 30 31 from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer, HashingVectorizer 32 33 from sklearn.decomposition import LatentDirichletAllocation 34 35 # LDA主题模型可视化 36 37 import pyLDAvis 38 39 import pyLDAvis.sklearn 40 41 import paddlenlp 42 43 data = pd.read_excel("data/data155443/xicha_meituan_data.xlsx") 44 45 # 词典文件路径 可以分特定词 如 46 47 dic_file = r"file/dict.txt" 48 49 stop_file = r"file/cn_stopwords.txt" 50 51 data.info() 52 53 # 去除无内容的评价 54 55 data = data.dropna() 56 57 data.head(5) 58 59 # 分词函数 60 61 def chinese_word_cut(mytext): 62 63 jieba.load_userdict(dic_file) 64 65 jieba.initialize() 66 67 try: 68 69 stopword_list = open(stop_file,encoding ='utf-8') 70 71 except: 72 73 stopword_list = [] 74 75 print("error in stop_file") 76 77 stop_list = [] 78 79 flag_list = ['n','nz','vn','a','an','ad','i'] 80 81 for line in stopword_list: 82 83 line = re.sub(u'\n|\\r', '', line) 84 85 stop_list.append(line) 86 87 88 89 word_list = [] 90 91 #jieba分词 92 93 seg_list = psg.cut(mytext,use_paddle=True) 94 95 for seg_word in seg_list: 96 97 word = seg_word.word 98 99 find = 0 100 101 if seg_word.flag == 'x': 102 103 find=1 104 105 for stop_word in stop_list: 106 107 if stop_word == word : 108 109 find = 1 110 111 break 112 113 if find == 0 : # and seg_word.flag in flag_list 114 115 word_list.append(word) 116 117 return (" ").join(word_list) 118 119 # 计算分词后文本的词频 120 121 def count_frequencies(word_list): 122 123 freq = dict() 124 125 for sentence in word_list: 126 127 for w in sentence.split(' '): 128 129 if w not in freq.keys(): 130 131 freq[w] = 1 132 133 else: 134 135 freq[w] += 1 136 137 return freq 138 139 data["cutted_comment"] = data.comment.apply(chinese_word_cut) 140 141 freq = count_frequencies(data["cutted_comment"]) 142 143 freq = sorted(freq.items(),key=lambda x:x[1],reverse=True) 144 145 freq[:15] 146 147 len(freq) 148 149 # 去除过短的评论 150 151 t_data = data[data['cutted_comment'].str.len()>5] 152 153 t_data = t_data.reset_index().drop(columns='index') 154 155 # 例子 156 157 t=time.localtime(1650933910610/1000) 158 159 time.strftime("%Y-%m-%d %H:%M:%S",t).split(' ') 160 161 _date=[] 162 163 _date_month=[] 164 165 _date_day=[] 166 167 _time=[] 168 169 _time_hour=[] 170 171 for i in t_data['comment_time']: 172 173 arr=time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(i/1000)).split(' ') 174 175 _date.append(arr[0]) 176 177 _date_month.append(arr[0].split('-')[1]) 178 179 _date_day.append(arr[0].split('-')[2]) 180 181 _time.append(arr[1]) 182 183 _time_hour.append(arr[1].split(':')[0]) 184 185 t_data.insert(2,value=_date_month,column='_date_month') 186 187 t_data.insert(3,value=_date_day,column='_date_day') 188 189 t_data.insert(4,value=_time_hour,column='_time_hour') 190 191 t_data.head(5) 192 193 sa = paddlenlp.Taskflow('sentiment_analysis') 194 195 sentiment_analysis_data = sa(t_data['comment'].to_list()) 196 197 sentiment_analysis_data_df = pd.DataFrame(sentiment_analysis_data) 198 199 sentiment_analysis_data_df.head(5) 200 201 t_data['label'] = sentiment_analysis_data_df['label'] 202 203 t_data['score'] = sentiment_analysis_data_df['score'] 204 205 # 保存一下 206 207 t_data.to_excel('file/data.xlsx',index=False,encoding='utf8') 208 209 t_data.head(5) 210 211 t_data.info() 212 213 def plt_imshow(x, ax=None, show=True): 214 215 if ax is None: 216 217 fig, ax = plt.subplots() 218 219 ax.imshow(x) 220 221 ax.axis("off") 222 223 if show: plt.show() 224 225 return ax 226 227 wcd = WordCloud(background_color='white', 228 229 max_words=200, 230 231 font_path = 'file/font/SIMHEI.TTF', 232 233 mode="RGBA", 234 235 max_font_size=180, 236 237 width = 1300, 238 239 height = 800, 240 241 scale=10 242 243 ) 244 245 wcd.generate_from_frequencies(dict(freq)) 246 247 ax=plt_imshow(wcd) 248 249 ax.figure.savefig('file/pic/wordcloud0.png',dpi=1000) 250 251 plt.figure(figsize=(19,6)) 252 253 ax=sns.countplot( 254 255 t_data['_date_month'], 256 257 saturation =1, 258 259 palette=sns.color_palette(palette='OrRd_d',desat=0.9,n_colors=12), 260 261 ) 262 263 plt.title('Number of monthly reviews of HEYTEA',fontsize=30) 264 265 plt.xlabel('Month',fontsize=30) 266 267 plt.ylabel("Count",fontsize=30) 268 269 plt.savefig('file/pic/每月评价数.png',dpi=1000) 270 271 plt.figure(figsize=(19,6)) 272 273 ax=sns.countplot( 274 275 t_data['_date_day'], 276 277 saturation =1, 278 279 palette=sns.color_palette(palette='PuBu',desat=1,n_colors=10) 280 281 ) 282 283 plt.title('Number of Daily reviews of HEYTEA',fontsize=30) 284 285 plt.xlabel('Day',fontsize=30) 286 287 plt.ylabel("Count",fontsize=30) 288 289 plt.savefig('file/pic/一个月中每日评价数.png',dpi=1000) 290 291 plt.figure(figsize=(19,6)) 292 293 ax=sns.countplot( 294 295 t_data['_time_hour'], 296 297 saturation=1, 298 299 palette=sns.color_palette(palette='OrRd_d',desat=1) 300 301 ) 302 303 plt.title('Number of Hours reviews of HEYTEA',fontsize=30) 304 305 plt.xlabel('Every hour of the day',fontsize=30) 306 307 plt.ylabel("Count",fontsize=30) 308 309 plt.savefig('file/pic/一个天中24小时评价数.png',dpi=1000) 310 311 # 消极评论每天各个时段散点图 312 313 plt.figure(figsize=(12,9)) 314 315 sns.swarmplot(y=t_data['_time_hour'],x=t_data['label']) 316 317 plt.title('HEYTEA Distribution of good and bad reviews in various time periods of the day',fontsize=15) 318 319 plt.xlabel('Label',fontsize=20) 320 321 plt.ylabel('per hours of day',fontsize=20) 322 323 plt.savefig('file/pic/一天内各个时段好差评数据分布.png',dpi=1000) 324 325 # 消极评论每个月散点图 326 327 plt.figure(figsize=(12,9)) 328 329 sns.swarmplot(y=t_data['_date_month'],x=t_data['label']) 330 331 # 消极评论每个月内散点图 332 333 plt.figure(figsize=(12,9)) 334 335 sns.swarmplot(y=t_data['_date_day'],x=t_data['label']) 336 337 sns.countplot(t_data['label']) 338 339 plt.title(r"HEYTEA Negative vs. positive reviews",fontsize=15) 340 341 plt.ylabel('Count',fontsize=15) 342 343 plt.xlabel('HEYTEA Comment Label',fontsize=15) 344 345 plt.savefig('file/pic/喜茶评价积极与消极比较.png',dpi=1000) 346 347 ax=sns.barplot( 348 349 y=[len(t_data['comment']),len(t_data['comment'].unique())], 350 351 x=['all_comment','unique_comment'], 352 353 ) 354 355 plt.title('HEYTEA comments''s uniqueness',fontsize=15) 356 357 plt.ylabel('Count',fontsize=15) 358 359 plt.savefig('file/pic/喜茶评价唯一性.png',dpi=1000) 360 361 print('消极评论占比',sum(t_data['label']=='negative')/len(t_data)) 362 363 # 消极评论词云图 364 365 freq_negative = count_frequencies(t_data[t_data['label']=='negative']['cutted_comment']) 366 367 freq_negative = sorted(freq_negative.items(),key=lambda x:x[1],reverse=True) 368 369 freq_negative[:15] 370 371 wcd = WordCloud(background_color='white', 372 373 max_words=150, 374 375 font_path = 'file/font/SIMHEI.TTF', 376 377 mode="RGBA", 378 379 max_font_size=160, 380 381 width = 1000, 382 383 height = 500, 384 385 scale=10) 386 387 wcd.generate_from_frequencies(dict(freq_negative[4:])) 388 389 ax=plt_imshow(wcd) 390 391 ax.figure.savefig('file/pic/wordcloud_negative.png',dpi=1000) 392 393 n_features = 1000 #提取1000个特征词语 394 395 cv_vectorizer = CountVectorizer(max_df = 0.90, 396 397 max_features=n_features, 398 399 min_df = 5) 400 401 cv = cv_vectorizer.fit_transform(t_data.cutted_comment) 402 403 # tfidf提取文本特征 404 405 tfidf_vectorizer = TfidfVectorizer(max_df = 0.95, 406 407 max_features=500) 408 409 tfidf = tfidf_vectorizer.fit_transform(t_data.cutted_comment) 410 411 hash_vectorizer = HashingVectorizer() 412 413 hashing = hash_vectorizer.fit_transform(data.cutted_comment) 414 415 plexs = [] 416 417 n_max_topics = 50 418 419 for i in range(1,n_max_topics): 420 421 print(i,end='..') 422 423 lda = LatentDirichletAllocation(n_components=i, 424 425 doc_topic_prior=1/i, 426 427 topic_word_prior=1/i, 428 429 learning_method='batch') 430 431 lda.fit(cv) 432 433 plexs.append(lda.perplexity(cv)) 434 435 n_t=50#区间最右侧的值。注意:不能大于n_max_topics 436 437 x=list(range(1,n_t)) 438 439 plt.plot(x,plexs[:n_t], linestyle='-.') 440 441 plt.xlabel("number of topics") 442 443 plt.ylabel("perplexity") 444 445 plt.legend(('perplexity_value')) 446 447 plt.title("LDA Model Perplexity Value") 448 449 plt.savefig('file/pic/PerplexityValue.png',dpi=1000) 450 451 plt.show() 452 453 n_topics = 4 454 455 lda = LatentDirichletAllocation(n_components=n_topics,max_iter=100, 456 457 doc_topic_prior=1/n_topics, 458 459 topic_word_prior=0.01, 460 461 learning_method='batch') 462 463 lda.fit(cv) 464 465 def print_top_words(model, feature_names, n_top_words): 466 467 tword = [] 468 469 for topic_idx, topic in enumerate(model.components_): 470 471 print("Topic #%d:" % topic_idx) 472 473 topic_w = " ".join([feature_names[i] for i in topic.argsort()[:-n_top_words - 1:-1]]) 474 475 tword.append(topic_w) 476 477 print(topic_w) 478 479 return tword 480 481 # 输出每个主题及其主题词 482 483 n_top_words = 15 484 485 cv_vectorizer_name = cv_vectorizer.get_feature_names() 486 487 topic_word = print_top_words(lda, cv_vectorizer_name, n_top_words) 488 489 # LDA模型还可以用于文本分类 490 491 topics=lda.transform(cv) 492 493 topic = [] 494 495 for t in topics: 496 497 topic.append("Topic #"+str(list(t).index(np.max(t)))) 498 499 t_data['概率最大的主题序号']=topic 500 501 t_data['每个主题对应概率']=list(topics) 502 503 t_data.to_excel("data_topic_test0.xlsx",index=False) 504 505 pyLDAvis.enable_notebook() 506 507 pic = pyLDAvis.sklearn.prepare(lda, cv,cv_vectorizer) 508 509 pyLDAvis.display(pic) 510 511 pyLDAvis.save_html(pic, 'file/pic/lda_pass'+str(n_topics)+'.html') 512 513 pyLDAvis.display(pic) 514 515 #去工作路径下找保存好的html文件