本章代碼建議在linux下面運行,windows下安裝gensim會比較麻煩。
我是在python3.5.2的pycharm下運行的
下面代碼的意思是從評論數據中抽取品牌是美的的數據(15-1)
- #-*- coding: utf-8 -*-
- import pandas as pd
- inputfile = '../data/huizong.csv' #評論彙總文件
- outputfile = '../data/meidi_jd.txt' #評論提取後保存路徑
- data = pd.read_csv(inputfile, encoding = 'utf-8')
- data = data[[u'評論']][data[u'品牌'] == u'美的']
- data.to_csv(outputfile, index = False, header = False, encoding = 'utf-8')
這裏一句話概括接下來的去重概念,文本去重和機械壓縮去重
文本去重指的是數據條之間的去重。
機械壓縮去重指的是數據條內部,詞語與詞語之間的去重。
下面代碼是用來文本去重的(15-2)。
- #-*- coding: utf-8 -*-
- import pandas as pd
- inputfile = '../data/meidi_jd.txt' #評論文件
- outputfile = '../data/meidi_jd_process_1.txt' #評論處理後保存路徑
- data = pd.read_csv(inputfile, encoding = 'utf-8', header = None)
- l1 = len(data)
- data = pd.DataFrame(data[0].unique())
- l2 = len(data)
- data.to_csv(outputfile, index = False, header = False, encoding = 'utf-8')
- print(u'刪除了%s條評論。' %(l1 - l2))
下面代碼的作用是把評論前面的評分刪除(15-3):
- #-*- coding: utf-8 -*-
- import pandas as pd
- #參數初始化
- inputfile1 = '../data/meidi_jd_process_end_負面情感結果.txt'
- inputfile2 = '../data/meidi_jd_process_end_正面情感結果.txt'
- outputfile1 = '../data/meidi_jd_neg.txt'
- outputfile2 = '../data/meidi_jd_pos.txt'
- data1 = pd.read_csv(inputfile1, encoding = 'utf-8', header = None) #讀入數據
- data2 = pd.read_csv(inputfile2, encoding = 'utf-8', header = None)
- print("data1=",data1[0])
- data1 = pd.DataFrame(data1[0].str.replace('.*?\d+?\\t ', '')) #用正則表達式修改數據
- data2 = pd.DataFrame(data2[0].str.replace('.*?\d+?\\t ', ''))#這裏的意思其實是用‘’(也就是代表什麼都沒有)來代替前面的符合特徵的字符串,等效於實現了刪除的功能
- print("###############################")
- print("data1=",data1[0])
- #以上正則表達式的效果,可以通過把正則篩選前後的data[0]分別輸出來進行比較
- data1.to_csv(outputfile1, index = False, header = False, encoding = 'utf-8') #保存結果
- data2.to_csv(outputfile2, index = False, header = False, encoding = 'utf-8')
接下來是進行分詞(詳細解釋請見代碼中註釋)(15-4)
- #-*- coding: utf-8 -*-
- import pandas as pd
- import jieba #導入結巴分詞,需要自行下載安裝
- #參數初始化
- inputfile1 = '../data/meidi_jd_neg.txt'
- inputfile2 = '../data/meidi_jd_pos.txt'
- outputfile1 = '../data/meidi_jd_neg_cut.txt'
- outputfile2 = '../data/meidi_jd_pos_cut.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)) #自定義簡單分詞函數,先識別句子中的中文單詞,然後把中文單詞通過空格連接起來
- #上面一句代碼中,s是入口參數,.join前面的空格表示把jieba庫處理過後的s中的詞語jieba.cut(s),用空格來連接。
- data1 = data1[0].apply(mycut) #通過“廣播”形式分詞,加快速度。
- data2 = data2[0].apply(mycut)
- data1.to_csv(outputfile1, index = False, header = False, encoding = 'utf-8') #保存結果
- data2.to_csv(outputfile2, index = False, header = False, encoding = 'utf-8')
最後是LDA代碼(15-5)
- #-*- coding: utf-8 -*-
- import pandas as pd
- #參數初始化
- negfile = '../data/meidi_jd_neg_cut.txt'
- posfile = '../data/meidi_jd_pos_cut.txt'
- stoplist = '../data/stoplist.txt'
- neg = pd.read_csv(negfile, encoding = 'utf-8', header = None) #讀入數據
- pos = pd.read_csv(posfile, encoding = 'utf-8', header = None)
- stop = pd.read_csv(stoplist, encoding = 'utf-8', header = None, sep = 'tipdm',engine='python')
- #sep設置分割詞,由於csv默認以半角逗號爲分割詞,而該詞恰好在停用詞表中,因此會導致讀取出錯(這裏的出錯的意思就是代碼運行報錯,編譯器直接不讓編譯通過)
- #所以解決辦法是手動設置一個不存在的分割詞,如tipdm。
- #這裏先解釋下什麼是“停用詞”,停用詞指的是本文中出現頻率很高、但是實際意義不大的詞語,比如
- #“今天好嗨森啊啊啊啊啊啊啊啊”,那麼這句話中的“啊啊啊啊啊啊啊啊”就是停用詞
- #講通俗點的話,停用詞就是“廢話”。 。
- stop = [' ', ''] + list(stop[0]) #Pandas自動過濾了空格符,這裏手動添加(在每條數據的開頭加個空格)
- #下面這段代碼可以分爲兩小段,這兩小段代碼幾乎一致,前面一個是針對負面評論,後一個是針對正面評論,所以只詳解其中一個
- neg[1] = neg[0].apply(lambda s: s.split(' ')) #定義一個分割函數,然後用apply廣播
- neg[2] = neg[1].apply(lambda x: [i for i in x if i not in stop]) #逐詞判斷是否停用詞,思路同上
- #上面這句代碼的語法是:列表推導式子。意思是說,如果i不在停用詞列表(stop)中,就保留該詞語(也就是最前面的一個i),否則就進行刪除
- #上面的這句代碼中,把for i in x看做整體,把if i not in stop看做判斷語句,把最前面的i看做滿足if語句之後的執行語句即可。
- pos[1] = pos[0].apply(lambda s: s.split(' '))
- pos[2] = pos[1].apply(lambda x: [i for i in x if i not in stop])
- #上面的lamda s和lamda x中的s和x都是表示入口參數,apply的意思是,把apply前面的字符串當做入口參數,輸入到appy後面所定義的函數中
- from gensim import corpora, models
- #負面主題分析
- #這段代碼和下面的“正面主題分析”幾乎是完全一樣的,作用講得通俗點其實就是聚類。
- neg_dict = corpora.Dictionary(neg[2]) #建立詞典
- neg_corpus = [neg_dict.doc2bow(i) for i in neg[2]] #建立語料庫
- neg_lda = models.LdaModel(neg_corpus, num_topics = 3, id2word = neg_dict) #LDA模型訓練
- for i in range(3):
- neg_lda.print_topic(i) #輸出每個主題(這個其實就是聚類結果的輸出)
- #正面主題分析
- pos_dict = corpora.Dictionary(pos[2])
- pos_corpus = [pos_dict.doc2bow(i) for i in pos[2]]
- pos_lda = models.LdaModel(pos_corpus, num_topics = 3, id2word = pos_dict)
- for i in range(3):
- neg_lda.print_topic(i) #輸出每個主題
通俗解釋下LDA算法幹嘛的,我們知道:
K-means是聚類的,他主要是處理數據的,對數據進行聚類。
LDA其實也是聚類的,主要是處理字符串的,對字符串進行聚類。