1. 程式人生 > >Python資料探勘——文字分析

Python資料探勘——文字分析

一、

一、定義:

文字挖掘:從大量文字資料中抽取出有價值的知識,並且利用這些知識重新組織資訊的過程。

二、語料庫(Corpus)

語料庫是我們要分析的所有文件的集合。

import os
import os.path

filePaths = []  #定義一個數組變數
#再用OS.walk的方法傳入目錄
#檔案所在的檔案目錄,命名為root
#root下的所有子目錄,命名為dirs
#root下的所有檔案,命名為files
for root, dirs, files in os.walk(
    "C:\\Python_DM\\2.1\\SogouC.mini\\Sample"
):
    #進行遍歷,需要得到輸入目錄下的所有檔案
    for name in files:  #為了拿到root目錄下的所有檔案,我們再次便利所有的檔案(程式碼:for name in files:)把它追加到filePaths變數中去即可。
        filePaths.append(os.path.join(root, name)) 
"""
os.path.join,拼接檔案路徑的方法。如果沒有name,則filepaths裡面沒有xx.txt檔案,沒有root則沒有檔案目錄路徑。
"""

import codecs  #編碼轉換

filePaths = [];
fileContents = [];
for root, dirs, files in os.walk(
    "C:\\Python_DM\\2.1\\SogouC.mini\\Sample"
):
    for name in files:
        filePath = os.path.join(root, name);
        filePaths.append(filePath);
        f = codecs.open(filePath, 'r', 'utf-8') #1.檔案路徑 2.開啟方式 3.檔案編碼
        fileContent = f.read()
        f.close()
        fileContents.append(fileContent)

import pandas;
corpos = pandas.DataFrame({
    'filePath': filePaths, 
    'fileContent': fileContents
})

二、中文分詞

2.1概念:

中文分詞(Chinese Word Segmentation):將一個漢字序列切分成一個一個單獨的詞。

eg:我的家鄉是廣東省湛江市-->我/的/家鄉/是/廣東省/湛江市

停用詞(Stop Words):
資料處理時,需要過濾掉某些字或詞
√氾濫的詞,如web、網站等。

√語氣助詞、副詞、介詞、連線詞等,如 的,地,得;

2.2安裝Jieba分詞包:

最簡單的方法是用CMD直接安裝:輸入pip install jieba,但是我的電腦上好像不行。

後來在這裡:https://pypi.org/project/jieba/#files下載了jieba0.39解壓縮後 放在Python36\Lib\site-packages裡面,然後在用cmd,pip install jieba 就下載成功了,不知道是是什麼原因。

然後我再anaconda 環境下也安裝了jieba,先在Anaconda3\Lib這個目錄下將jieba0.39的解壓縮檔案放在裡面,然後在Anaconda propt下輸入 pip install jieba,如下圖:

2.3程式碼實戰:

jieba最主要的方法是cut方法:

  • jieba.cut方法接受兩個輸入引數: 1) 第一個引數為需要分詞的字串 2)cut_all引數用來控制是否採用全模式

  • jieba.cut_for_search方法接受一個引數:需要分詞的字串,該方法適合用於搜尋引擎構建倒排索引的分詞,粒度比較細

  • 注意:待分詞的字串可以是gbk字串、utf-8字串或者unicode

  • jieba.cut以及jieba.cut_for_search返回的結構都是一個可迭代的generator,可以使用for迴圈來獲得分詞後得到的每一個詞語(unicode),也可以用list(jieba.cut(...))轉化為list程式碼示例( 分詞 )

import jieba;

for w in jieba.cut("我愛Python"):
    print(w)
輸出結果為:


Python

for w in jieba.cut("""
    工信處女幹事
    每月經過下屬科室都要親口交代
    24口交換機等技術性器件的安裝工作
"""):
    print(w)
工信處

女幹事

每月
經過
下屬
科室


親口

交代

24

交換機

技術性
器件

安裝

工作

分詞功能用於專業的場景:

import jieba;
seg_list = jieba.cut(
    "真武七截陣和天罡北斗陣哪個更厲害呢?"
)
for w in seg_list:
    print(w)
會出現真武七截陣和天罡北斗陣被分成幾個詞。為了改善這個現象,我們用匯入詞庫的方法。
import jieba;
jieba.add_word('真武七截陣')#新增詞庫
jieba.add_word('天罡北斗陣')
seg_list = jieba.cut(
    "真武七截陣和天罡北斗陣哪個更厲害呢?"
)
for w in seg_list:
    print(w)

但是,如果需要匯入的單詞很多,jieba.add_word()這樣的新增詞庫的方法就不高效了。

我們可以用jieba.load_userdict(‘D:\\PDM\\2.2\\金庸武功招式.txt’)方法一次性匯入整個詞庫,txt檔案中為每行一個特定的詞。

2.3.1對大量文章進行分詞

先搭建語料庫:

分詞後我們需要對資訊處理,就是這個分詞來源於哪個文章。

三、詞頻統計

3.1詞頻(Term Frequency):

    某個詞在該文件中出現的次數。

3.2利用Python進行詞頻統計

# -*- coding: utf-8 -*-
"""搭建語料庫,及分詞"""
import os
import os.path
import codecs

filePaths = []
fileContents = []
for root, dirs, files in os.walk(
    "C:\\Python_DM\\2.1\\SogouC.mini\\Sample"
):
    for name in files:
        filePath = os.path.join(root, name)
        filePaths.append(filePath);
        f = codecs.open(filePath, 'r', 'utf-8')
        fileContent = f.read()
        f.close()
        fileContents.append(fileContent)

import pandas;
corpos = pandas.DataFrame({
    'filePath': filePaths, 
    'fileContent': fileContents
});

import jieba

segments = []
filePaths = []
for index, row in corpos.iterrows():
    filePath = row['filePath']
    fileContent = row['fileContent']
    segs = jieba.cut(fileContent)
    for seg in segs:
        segments.append(seg)
        filePaths.append(filePath)

segmentDataFrame = pandas.DataFrame({
    'segment': segments, 
    'filePath': filePaths
})

"""filepath一直沒變,對fileContents進行了分詞,賦值如segment."""


import numpy
#進行詞頻統計        
segStat = segmentDataFrame.groupby( #呼叫groupby方法
            by="segment"
        )["segment"].agg({
            "計數":numpy.size
        }).reset_index().sort_values(#重新設定索引
            by=['計數'],
            ascending=False#倒序排序
        )
"""排在前面的為停用詞"""

#移除停用詞
stopwords = pandas.read_csv(
    "C:\\Python_DM\\2.3\\StopwordsCN.txt", 
    encoding='utf8', 
    index_col=False
)

#獲得沒有停用詞的詞頻統計結果
fSegStat = segStat[
    ~segStat.segment.isin(stopwords.stopword)
]#'~'取反,不包含停用詞的留下。

3.2.1移除停用詞的另一種方法,加if判斷

import os
import os.path
import codecs

filePaths = []
fileContents = []
for root, dirs, files in os.walk(
    "C:\\Python_DM\\2.1\\SogouC.mini\\Sample"
):
    for name in files:
        filePath = os.path.join(root, name)
        filePaths.append(filePath);
        f = codecs.open(filePath, 'r', 'utf-8')
        fileContent = f.read()
        f.close()
        fileContents.append(fileContent)

import pandas;
corpos = pandas.DataFrame({
    'filePath': filePaths, 
    'fileContent': fileContents
});
import jieba

segments = []
filePaths = []
for index, row in corpos.iterrows():
    filePath = row['filePath']
    fileContent = row['fileContent']
    segs = jieba.cut(fileContent)
    for seg in segs:#下面加一個判斷,如果不在分詞中就加入進分組,加一個條件:分詞去除空格後的長度大於0
        if seg not in stopwords.stopword.values and len(seg.strip())>0:
            segments.append(seg)
            filePaths.append(filePath)

segmentDataFrame = pandas.DataFrame({
    'segment': segments, 
    'filePath': filePaths
});

segStat = segmentDataFrame.groupby(
            by="segment"
        )["segment"].agg({
            "計數":numpy.size
        }).reset_index().sort_values(
            by=["計數"],
            ascending=False
        );

程式碼中用到的一些常用方法:

分組統計:

DataFrame.groupby(
        by=列名陣列)[統計列明陣列].agg({
                '統計項名稱':統計函式
                })
判斷一個數據框中的某一列的值是否包含一個數組中的任意一個值:
DataFrame.列名.isin(陣列)
取反:(對布林值)
df[~df.列名.isin(陣列)]

四、詞雲繪製
詞雲(Word Cloud):是對文字中詞頻較高的分詞,給與視覺上的突出,形成“關鍵詞渲染”,從而國旅掉大量的文字資訊,使瀏覽者一眼掃過就可以領略文字的主旨。

4.1安裝詞雲工具包
這個地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/ ,可以搜到基本上所有的Python庫,進去根據自己的系統和Python的版本進行下載即可。

在python下安裝很方便,在anaconda下安裝費了點勁,最終將詞雲的檔案放在C:\Users\Administrator 這個目錄下才安裝成功。

# -*- coding: utf-8 -*-
import os;
import os.path;
import codecs;

filePaths = [];
fileContents = [];
for root, dirs, files in os.walk(
    "C:\\Python_DM\\2.4\\SogouC.mini\\Sample\\C000007"
):
    for name in files:
        filePath = os.path.join(root, name);
        filePaths.append(filePath);
        f = codecs.open(filePath, 'r', 'utf-8')
        fileContent = f.read()
        f.close()
        fileContents.append(fileContent)

import pandas;
corpos = pandas.DataFrame({
    'filePath': filePaths, 
    'fileContent': fileContents
});

import jieba

segments = []
filePaths = []
for index, row in corpos.iterrows():
    filePath = row['filePath']
    fileContent = row['fileContent']
    segs = jieba.cut(fileContent)
    for seg in segs:
        segments.append(seg)
        filePaths.append(filePath)

segmentDataFrame = pandas.DataFrame({
    'segment': segments, 
    'filePath': filePaths
});


import numpy;
#進行詞頻統計        
segStat = segmentDataFrame.groupby(
            by="segment"
        )["segment"].agg({
            "計數":numpy.size
        }).reset_index().sort_values(
            by=["計數"],
            ascending=False
        );

#移除停用詞
stopwords = pandas.read_csv(
    "C:\\Python_DM\\2.4\\StopwordsCN.txt", 
    encoding='utf8', 
    index_col=False
)

fSegStat = segStat[
    ~segStat.segment.isin(stopwords.stopword)
]

#繪畫詞雲
#http://www.lfd.uci.edu/~gohlke/pythonlibs/
from wordcloud import WordCloud
import matplotlib.pyplot as plt

#傳入字型檔案的路徑,還有背景顏色
#微軟雅黑的字型,黑色背景
wordcloud = WordCloud(
    font_path='C:\\Python_DM\\2.4\\simhei.ttf', 
    background_color="black"
)

#把分詞設定成資料框的索引,再呼叫to_dict()的方法,獲得一個字典的資料結構了。
words = fSegStat.set_index('segment').to_dict()

wordcloud.fit_words(words['計數'])

plt.imshow(wordcloud)

#plt.close()
五、美化詞雲(詞雲放入某圖片形象中)
六、關鍵詞提取
import os
import codecs
import pandas
import jieba
import jieba.analyse #關鍵字提取方法

#定義好儲存的列陣列,抽取5個關鍵字
filePaths = []
contents = []
tag1s = []
tag2s = []
tag3s = []
tag4s = []
tag5s = []

for root, dirs, files in os.walk(
    "C:\\Python_DM\\2.6\\SogouC.mini\\Sample\\"
):
    for name in files:
        filePath = root + '\\' + name;
        f = codecs.open(filePath, 'r', 'utf-8')
        content = f.read().strip()
        f.close()
        
        #將檔案內容(content)傳遞給extract_tags方法
        #把管家你在tags新增到對應的列中
        tags = jieba.analyse.extract_tags(content, topK=5)
        filePaths.append(filePath)
        contents.append(content)
        tag1s.append(tags[0])
        tag2s.append(tags[1])
        tag3s.append(tags[2])
        tag4s.append(tags[3])
        tag5s.append(tags[4])

tagDF = pandas.DataFrame({
    'filePath': filePaths, 
    'content': contents, 
    'tag1': tag1s, 
    'tag2': tag2s, 
    'tag3': tag3s, 
    'tag4': tag4s, 
    'tag5': tag5s
})
結果如下:

七、關鍵詞提取實現

詞頻(Term Frequency):

    指的是某一個給定的詞在該文件中出現的次數。

計算公式: TF = 該次在文件中出現的次數

逆文件頻率(Inverse Document Frequency)

    IDF就是每個詞的權重,它的大小與一個詞的常見程度成反比。

計算公式:IDF = log(文件總數/(包含該詞的文件數 - 1))

TF-IDF(Term Frequency-Inverse Document Frequency)

    權衡某個分詞是否關鍵詞的指標,該值越大,是關鍵詞的可能性就越大。

計算公式:TF - IDF = TF * IDF

7.1文件向量化


7.2程式碼實戰