1. 程式人生 > >《Python資料分析與挖掘實戰》第15章——文字挖掘

《Python資料分析與挖掘實戰》第15章——文字挖掘

本文是基於《Python資料分析與挖掘實戰》的實戰部分的第15章的資料——《電商產品評論資料情感分析》做的分析。

旨在回顧對評論文字資料的處理和建模方法。

1 挖掘背景與目標

    對京東平臺上的熱水器評論進行文字挖掘分析,挖掘建模如下:

1)分析某一個品牌熱水器的使用者情感傾向

2)從評論文字中挖掘出該品牌熱水器的優點和不足

3)提煉不同品牌熱水器的賣點

2 資料探索與預處理

2.1 資料篩選

# -*- coding:utf-8 -*-
import pandas as pd
inputfile = 'huizong.csv' # 評論彙總檔案
data = pd.read_csv(inputfile, encoding = 'utf-8')
result = data[[u'評論']][data[u'品牌'] == u'美的']
result.info()

輸出結果

2.2 to_txt

# 必須匯入下面這個包,要不然會報錯'ascii' codec can't encode characters in position
# Python在安裝時,預設的編碼是ascii,當程式中出現非ascii編碼時,python的處理常常會報這樣的錯
import sys
reload(sys)
sys.setdefaultencoding( "utf-8" )
result.to_csv('1_1my_meidi_jd.txt', index = False, header = False) # 將評論提取後儲存到txt中,不要索引,不要列名(***)

2.3 原始資料去重

import pandas as pd
inputfile = '1_1my_meidi_jd.txt' # 評論彙總檔案
data = pd.read_csv(inputfile, encoding = 'utf-8', header = None) #(***)
l1 = len(data) 
print u'原始資料有%d條' % l1  # 原始資料有55774條 
data = pd.DataFrame(data[0].unique())# (*****)
l2 = len(data)
print u'去重後資料有%d條' % l2 # 去重後資料有53049條
data.to_csv('2_1my_meidi_jd_delduplis.txt', header = False, index = False, encoding='utf-8') # (***)

2.4 刪除字首

inputfile1 = u'meidi_jd_process_end_負面情感結果.txt' # 評論彙總檔案
inputfile2 = u'meidi_jd_process_end_正面情感結果.txt' # 評論彙總檔案

data1 = pd.read_csv(inputfile1, encoding = 'utf-8', header = None) #(***)
data2 = pd.read_csv(inputfile2, encoding = 'utf-8', header = None) #(***)

data1 = pd.DataFrame(data1[0].str.replace('.*?\d+?\\t', '')) # 使用正則表示式替換掉字首
data2 = pd.DataFrame(data2[0].str.replace('.*?\d+?\\t', '')) # 使用正則表示式替換掉字首

data1.to_csv(u'3_1my_meidi_jd_process_end_負面情感結果.txt', header = False, index = False, encoding='utf-8') # (***)
data2.to_csv(u'3_2my_meidi_jd_process_end_正面情感結果.txt', header = False, index = False, encoding='utf-8') # (***)

2.5 分詞

import pandas as pd
import jieba # 匯入結巴分詞包

inputfile1 = u'3_1my_meidi_jd_process_end_負面情感結果.txt' 
inputfile2 = u'3_2my_meidi_jd_process_end_正面情感結果.txt'
data1 = pd.read_csv(inputfile1, encoding = 'utf-8', header = None) #(***)
data2 = pd.read_csv(inputfile2, encoding = 'utf-8', header = None) #(***)

mycut = lambda s: " ".join(jieba.cut(s)) # 自定義簡單分詞函式
data1 = data1[0].apply(mycut) # 通過廣播形式分詞,加快速度
data2 = data2[0].apply(mycut) # 通過廣播形式分詞,加快速度

data1.to_csv(u'4_1my_meidi_jd_process_end_負面情感結果_cut.txt', header = False, index = False, encoding='utf-8') # (***)
data2.to_csv(u'4_2my_meidi_jd_process_end_正面情感結果_cut.txt', header = False, index = False, encoding='utf-8') # (***)

3 基於LED 模型的主題分析

# 方法:在分好詞的正面評價、負面評價以及過濾用的停用詞表上進行,使用Gensim庫完成LDA分析程式碼
import pandas as pd

# 引數初始化
inputfile1 = u'4_1my_meidi_jd_process_end_負面情感結果_cut.txt' 
inputfile2 = u'4_2my_meidi_jd_process_end_正面情感結果_cut.txt'
inputfile3 = 'stoplist.txt' # 停用詞表

data1 = pd.read_csv(inputfile1, encoding = 'utf-8', header = None) #(***)
data2 = pd.read_csv(inputfile2, encoding = 'utf-8', header = None) #(***)
stop = pd.read_csv(inputfile3, encoding = 'utf-8', sep = 'tipdm', header = None) #(***)
# sep 設定分割詞, 由於csv預設以半形逗號為分割詞,而該詞恰好在停用詞表中,因此會導致讀取出錯
# 所以,解決方法是手動設定一個不存在的分割詞,如tipdm
stop = [' ', ''] +list(stop[0]) # pandas自動過濾了空格符,所以手動將其加入

data1 [1] = data1[0].apply(lambda s: s.split(' ')) # 定義一個分隔函式,用apply廣播
data1 [2] = data1[1].apply(lambda x: [i for i in x if i not in stop]) # 逐詞判斷是否是停用詞

data2 [1] = data2[0].apply(lambda s: s.split(' ')) # 定義一個分隔函式,用apply廣播
data2 [2] = data2[1].apply(lambda x: [i for i in x if i not in stop]) # 逐詞判斷是否是停用詞
from gensim import corpora, models
# 負面主題分析
data1_dict = corpora.Dictionary(data1[2]) # 建立詞典
data1_corpus = [data1_dict.doc2bow(i) for i in data1[2]] # 建立語料庫

data1_LDA = models.LdaModel(data1_corpus, num_topics =3, id2word = data1_dict) # LDA訓練模型
for i in range(3):
    data1_LDA.print_topic(i)# 輸出每個主題
# 正面主題分析
data2_dict = corpora.Dictionary(data2[2]) # 建立詞典
data2_corpus = [data2_dict.doc2bow(i) for i in data2[2]] # 建立語料庫

data2_LDA = models.LdaModel(data2_corpus, num_topics =3, id2word = data2_dict) # LDA訓練模型
for i in range(3):
    data2_LDA.print_topic(i)# 輸出每個主題
PS:不知道為什麼輸出時有編碼問題

data1_LDA.print_topic(0)

輸出:

u'0.044*"\u7684" + 0.036*"\u8fd8" + 0.027*"\u5b89\u88c5" + 0.024*"\u4e86" + 0.021*"\u5f88" + 0.019*"\u4e0d\u9519" + 0.015*"\u4e0d" + 0.013*"\u7528" + 0.011*"\u597d" + 0.011*"\u5c31\u662f"'

備註:本章完整程式碼請見:點選開啟連結