1.背景介紹
美賽C題涉及到文本處理之間的工作,筆者學藝不精,廣爲蒐羅了很多代碼加以完善改進,封裝成一個個的函數,這些函數都很有針對性,主要應用於文本預處理包括,排序、分詞、獲取語料庫、去標點、統計詞頻、特徵提取、詞性還原、去停用詞等。
2.任務分析
爲了更好地瞭解代碼,我們首先來認識一下數據集的格式。
文中涉及三個數據集microwave.tsv,hair_dryer.tsv, pacifier.tsv
表頭都是一樣的,以pacifier(奶嘴)爲例。
我們要用到的有如下幾列。
3.Pyhton代碼
庫引用
#代碼所涉及到的庫(部分,其餘爲引用的將在後面引用)
import numpy as np
import pandas as pd
import re
from os import path
import matplotlib.pyplot as plt
import jieba
數據讀取
讀取數據,由於文件格式不是常見的csv,而且也不必讀取全部的列,
因此筆者編寫了一個新的函數,用於讀取特定文件特定列的數據
def getData(filename,cols):
train=pd.read_csv(filename, sep='\t',header=0,usecols=cols)
return train
小寫化並排序
如上圖所示我們只需要對train的4-7列小寫化並排序
def sortLow(train):
for i in range(3):
train.iloc[:,i+4]=train.iloc[:,i+4].str.lower()
train=train.sort_values(by=["vine",'verified_purchase'],ascending=False)
train=train.reindex(list(range(len(train))))#排序後索引會亂掉我們重置索引
return train
刪除過短的評論記錄
review_body列中包含用戶的評論內容,我們希望刪除評論內容小於三個單詞的行
#對字符串中單詞計數
def count_words(series):
len_li=[]
for string in series:
string=str(string)
string=string.split(' ')#將文章按照空格劃分開
len_li.append(len(string))
return pd.Series(len_li)
#刪除小於三個單詞的評論
train['counts']=count_words(train.review_body)
train=train[train.counts>3]
獲取簡單的語料庫
我們希望將所有評論彙總到一起,組成一個語料庫。
from string import punctuation
punc=punctuation
#去除標點和數字
def text_save(filename, data):#filename爲寫入CSV文件的路徑,data爲要寫入數據列表.
file = open(filename,'a')
for line in data:
line=str(line)
line = re.sub(r"[{}]+".format(punc)," ",line)#正則匹配標點
line = re.sub(r"\d+"," ",line)#正則匹配數字
file.write(line+" ")
file.close()
print("保存文件成功")
#獲取詞典
def getDicCsv(name):
review_body=train['review_body']
review_body=list(review_body)#將評論存入列表
text_save(name,review_body)
調用getDicCsv函數之後我們就獲得了一個txt的語料庫
分詞
#分詞
import jieba
def dis(path):
text = open(path, encoding='utf-8').read()
text_cut=jieba.cut(text)
return text_cut
上述代碼用於將txt文件分成單個詞語列表
def rmSym(Series):#去除標點符號存入列表
lis=[]
for line in Series:
line=str(line)
line=line.lower()
line = re.sub(r"[{}]+".format(punc)," ",line)
line = re.sub(r"\d+"," ",line)
lis.append(line)
return lis
上述代碼用於對一個單獨的Series進行分詞處理,對於train[‘review_body’],該函數會輸出一個二維列表,每個子列表都對應一條評論的分詞結果
詞頻統計
#詞頻統計
def getWordFre(wordList,num):
#輸入詞語列表和獲取top詞數量
word_counts = collections.Counter(wordList) # 對分詞做詞頻統計
word_counts = word_counts.most_common(num) # 獲取前n最高頻的詞
return word_counts#返回詞頻列表
輸入詞語列表和數量,輸出一個詞頻列表,長度爲num,詞頻從大到小排列。
詞形還原
from nltk import word_tokenize, pos_tag
from nltk.corpus import wordnet
from nltk.stem import WordNetLemmatizer
def get_wordnet_pos(tag):
if tag.startswith('J'):
return wordnet.ADJ
elif tag.startswith('V'):
return wordnet.VERB
elif tag.startswith('N'):
return wordnet.NOUN
elif tag.startswith('R'):
return wordnet.ADV
else:
return None
#詞形還原輸出列表
def lem(sentence):
# 獲取單詞的詞性
tokens = word_tokenize(sentence) # 分詞
tagged_sent = pos_tag(tokens) # 獲取單詞詞性
wnl = WordNetLemmatizer()
lemmas_sent = []
for tag in tagged_sent:
wordnet_pos = get_wordnet_pos(tag[1]) or wordnet.NOUN
lemmas_sent.append(wnl.lemmatize(tag[0], pos=wordnet_pos)) # 詞形還原
return lemmas_sent
對二維列表進行詞形還原並展開成一維列表
def pureList(data_list):
lem_list=[]
for i in data_list:
lem_list = lem_list+lem(i)
return lem_list#返回詞形還原後的一維列表
去停用詞
from nltk.corpus import stopwords
stop_words=stopwords.words('english')
noStopList = [word for word in wod_list if(word not in stop_words)]
特徵提取
from sklearn.feature_extraction.text import CountVectorizer
#語料
corpus = noStopList
#將文本中的詞語轉換爲詞頻矩陣
vectorizer = CountVectorizer()
#計算個詞語出現的次數
X = vectorizer.fit_transform(corpus)
#獲取詞袋中所有文本關鍵詞
word = vectorizer.get_feature_names()
#查看詞頻結果
X.toarray()
word
from sklearn.feature_extraction.text import TfidfTransformer
#類調用
transformer = TfidfTransformer()
print(transformer)
#將詞頻矩陣X統計成TF-IDF值
tfidf = transformer.fit_transform(X)
#查看數據結構 tfidf[i][j]表示i類文本中的tf-idf權重
tfidf_arr=tfidf.toarray()
import heapq
#獲取一個一維數組中最大的n個詞
por=list(por)
#此時por爲[0,0,2.333,0,...,4.56.0,2,1,3.23...]好長的一個列表
re2 = map(por.index, heapq.nlargest(300, por))
#求最大的n個索引 nsmallest與nlargest相反,求最小
#注意re2是一個map對象
拆分日期列
#如果review_date數據格式爲datetime要轉化成字符串形式
train['year']=train['review_date'].apply(lambda x:x.split('/')[2])
train['month']=train['review_date'].apply(lambda x:x.split('/')[0])
然後可以根據dataframe索引篩選特定年月的數據,也可以運用groupby方法進行分類彙總
獲取特定年月的詞頻
def get_month_review_word_fre(year,month,dataframe,fre_num):
year=str(year);month=str(month)
test=train[train['year']==year]
test=test[test.month==month]
test=test.review_body
test=rmSym(test)
pureSenList=[]
for sen in test:
tem=lem(sen,stop_words)
pureSenList+=tem
word_fre=getWordFre(pureSenList,fre_num)
return word_fre
將輸出year年month月所有評論的前fre_num個詞頻
4.聲明
- 上文的函數中存在函數中調用函數的情況,請讀者注意。
- 歡迎廣大讀者在留言區指正錯誤,提出意見,如果認爲本文對您有幫助可以加個關注點個小贊,不勝感激。
- 這些代碼的原型的原鏈接已經難以找到,筆者希望原作者能夠私信的形式告知筆者,以便筆者在借鑑中聲明。