2020美賽C題賽後總結之——文本預處理Pyhotn編程代碼

1.背景介紹

美賽C題涉及到文本處理之間的工作,筆者學藝不精,廣爲蒐羅了很多代碼加以完善改進,封裝成一個個的函數,這些函數都很有針對性,主要應用於文本預處理包括,排序、分詞、獲取語料庫、去標點、統計詞頻、特徵提取、詞性還原、去停用詞等。

2.任務分析

爲了更好地瞭解代碼,我們首先來認識一下數據集的格式。
文中涉及三個數據集microwave.tsv,hair_dryer.tsv, pacifier.tsv
表頭都是一樣的,以pacifier(奶嘴)爲例。
我們要用到的有如下幾列。pacifier.tsv讀取後預覽

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

小寫化並排序

fig1
如上圖所示我們只需要對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

fig2

刪除過短的評論記錄

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]

fig3

獲取簡單的語料庫

我們希望將所有評論彙總到一起,組成一個語料庫。

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.聲明

  1. 上文的函數中存在函數中調用函數的情況,請讀者注意。
  2. 歡迎廣大讀者在留言區指正錯誤,提出意見,如果認爲本文對您有幫助可以加個關注點個小贊,不勝感激。
  3. 這些代碼的原型的原鏈接已經難以找到,筆者希望原作者能夠私信的形式告知筆者,以便筆者在借鑑中聲明。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章