【挖掘篇】:文本分析

# 词频统计(某一个给定的词在该文档中出现次数)
    # 语料库         分析的所有文档的集合
    # 中文分词       一个汉字序列切分成一个个单词
    # 停用词         数据处理的时候,自动过滤掉的某些字或词,包括泛滥的词,如:web,网站,语气助词,副词,介词,连接词
    # 文件读取API
        # 构建方法:os.walk(fileDir_文件夹路劲)
        # 文件读取:codecs.open(filePath_文件路劲,method_文件的打开方式(r_只读 w_写 rw_读写),encoding_文件的编码,使用UTF-8)
            # 用codes 提供的open 方法来打开文件的语言编码,读取时候回自动换换unicode,不然是乱码
    # 中文分词API
        # 安装方式: pip install jieba
        # 分词方法: jieba.cut(connent_需要分词的句子)
            # 返回  segments 分词的数组

    # 词云统计API
        # 安装方式:pip install wordcloud
        # 绘制方法:
            # 生成wordcloud 对象
                # wordcloud = WordCloud(font_path = 'simhei.ttf_中文字体',background_color = ‘black_背景颜色黑色’)
            # 进行绘制
                # wordcloudImg = wordcloud.fit_words(tuples)

    # 关键词  一篇文档的关键词通常是几个词或者短语,作为对该文档主要内容提要
    # 词频 TF = 某个词在该文档中出现的次数
    # 逆文档频率 IDF就是每个词的权重,它的大小与一个词的常见程度成反比 IDF = log (文档总数/(包含该词的文档数+1))
    # TF-IDF = TF * IDF  权衡某个分词是否关键词的指标,该值越大,是关键词的可能性越大
    
    # 案例:马尔科夫模型在中文分词中的应用,“马尔科夫模型” 和 "中文分词" 的TF一样,那个适合关键词
    
        # 用统计学语言表达,就是在词频的基础上,对每个词分配一个权重
            # 常见的词“的,是,在” 给予最小的权重
            # 较常见的词 “中文分词” 给予较小的权重
            # 较少见的词 “马尔科夫模型” 给予较大的权重

    # 自动摘要  全面准确的反映某一文献中心内容地简单连贯的短文 
     # 算法步骤
         # 获取到需要摘要的文章
         # 对文章进行词频统计
         # 对文中进行分句,根据中文的标点符号,一般我们采用“。”,“、”?” 分句
         # 计算分句和文章之间的余弦相似度
         # 取相似度最高的分句,作为文章摘要

    # 相似文章推荐  用户阅读某篇文章的时候,为用户推荐更多与在读文章在内容相似的文章
    
    # 推荐 介绍好的人或者事物,希望被任用或接受,在目前的数据挖掘领域,推荐包括相似推荐和协同过滤推荐
        # 相似推荐  当用户对某人或者某物感兴趣时,为它推荐与之相似的人或者物,人以群分,物以类聚
        # 协同过滤推荐 利用已有用户群过去的行为或者意见,预测当前用户最可能喜欢那些东西或者对哪些东西感兴趣
    # 余弦相似度 用向量空间中两个向量夹角的余弦值作为衡量两个个体间差异的大小。余弦值越接近1,说明夹角越相似,两个向量越相似
        # cos(e) = ∑(xi * yi) / (√∑(xi)^2 * √∑(yi)^2)
    # 案例:
        # 文章A 放假我喜欢弹吉他,看书 --分词--> 放假 我 喜欢 弹 吉他 看书
        # 文章B 放假我不喜欢看书,大球 --分词--> 放假 我 不 喜欢 看书 喜欢 吉他
            # 语料库 放假 我 喜欢 弹 吉他 看书 不 打球
        # 向量化(统计词频)
            # 文章A 【1 1 1 1 1 1 0 0】
            # 文章B 【1 1 2 0 0 1 1 1】
        # 计算
            # = (1*1+1*1+1*2+1*0+1*0+1*1+0*1+0*1)/√(1^2+1^2+1^2+1^2+1^2+1^2+0^2+0^2) * √(1^2+1^2+2^2+0^2+0^2+1^2+1^2+1^2)
            # 越小越相似

中文分词

Paste_Image.png
import jieba;

#http://pinyin.sogou.com/dict/    搜狗词库 ,下载为scel 文件 --》深蓝词库转换(无拼音纯单词) --》 txt 文件

seg_list = jieba.cut("真武七截阵和天罡北斗阵哪个更厉害呢?")
print(", ".join(seg_list)) # 将列表中的每个通过,打印出来

jieba.load_userdict('F:\\python 数据挖掘分析实战\\Code\\金庸武功招式.txt'); # 载入词库,正确的分词

seg_list = jieba.cut("真武七截阵和天罡北斗阵哪个更厉害呢?")
print(", ".join(seg_list))

词云绘制

import os
import os.path
os.getcwd()
os.chdir('F:\\python 数据挖掘分析实战\\Code')
import codecs
import numpy
import pandas
import jieba

#创建语料库
corpos = pandas.DataFrame(columns=['filePath', 'content'])

# 读取一个文件夹中的txt
for root, dirs, files in os.walk(
# root_起始路径   dirs_起始路径文件夹   files_qisi
    "F:\\python 数据挖掘分析实战\\Data\\SogouC.mini\\Sample\\C000007\\"
):
    for name in files:
        filePath = root + '\\' + name;
        f = codecs.open(filePath, 'r', 'utf-8')
        content = f.read()
        f.close()
        corpos.loc[len(corpos)] = [filePath, content.strip()]; # 数据框自动增加一行值
        
import re
#匹配中文的分词
zhPattern = re.compile(u'[\u4e00-\u9fa5]+')

#进行分词

filePaths = []
segments = []

for i in range(len(corpos)):
    filePath = corpos.loc[i].filePath  # corpos.loc[i] 第i行 .filePath 列
    segs = jieba.cut(corpos.loc[i].content)
    for seg in segs:
        if zhPattern.search(seg): # search方法可以返回第一个满足要求的字符串。一旦找到符合要求的内容,它就会停止查找
            filePaths.append(filePath) # 当放入seg的循环时候,就可以实现一对多
            segments.append(seg)
            
segmentDF = pandas.DataFrame({'filePath':filePaths, 'segment':segments})

#进行词频统计        
segStat = segmentDF.groupby(
            by="segment"
        )["segment"].agg({
            "计数":numpy.size
        }).reset_index().sort(
            columns=["计数"],
            ascending=False
        );

#移除停用词
stopwords = pandas.read_csv(
    "F:\\python 数据挖掘分析实战\\Code\\StopwordsCN.txt", 
    encoding='utf8', 
    index_col=False,
    quoting=3,
    sep="\t"
)

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

#绘画词云
#http://www.lfd.uci.edu/~gohlke/pythonlibs/
# pip install wordcloud-1.2.1-cp35-cp35m-win32.whl
from wordcloud import WordCloud
import matplotlib.pyplot as plt

wordcloud = WordCloud(
    font_path='F:\\python 数据挖掘分析实战\\Code\\simhei.ttf', 
    background_color="black"
)

wordcloud = wordcloud.fit_words(fSegStat.itertuples(index=False))

plt.imshow(wordcloud)

plt.close()

关键词提取

【挖掘篇】:文本分析_第1张图片
Paste_Image.png
import os
import os.path
import codecs
import numpy
import pandas
import jieba

#创建语料库
corpos = pandas.DataFrame(columns=['filePath', 'content'])

for root, dirs, files in os.walk(
    "F:\\python 数据挖掘分析实战\\Data\\SogouC.mini\\Sample\\"
):
    for name in files:
        filePath = root + '\\' + name;
        f = codecs.open(filePath, 'r', 'utf-8')
        content = f.read()
        f.close()
        corpos.loc[len(corpos)] = [filePath, content.strip()];

import re
#匹配中文的分词
zhPattern = re.compile(u'[\u4e00-\u9fa5]+')  # 匹配中文

#进行分词
filePaths = []
segments = []
for i in range(len(corpos)):
    filePath = corpos.loc[i].filePath
    segs = jieba.cut(corpos.loc[i].content)
    for seg in segs:
        if zhPattern.search(seg):
            filePaths.append(filePath); # 直接引用该层
            segments.append(seg);

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

#移除停用词
stopwords = pandas.read_csv(
    "F:\\python 数据挖掘分析实战\\Code\\StopwordsCN.txt", 
    encoding='utf8', 
    index_col=False,
    quoting=3,
    sep="\t"
)

segmentDF = segmentDF[~segmentDF.segment.isin(stopwords.stopword)]

#按文章进行词频统计,select filePath,segment,count(*) as 计数 from segmentDF group by filePath,segment
# 每个文章的词频
segStat = segmentDF.groupby(
            by=["filePath", "segment"]
        )["segment"].agg({
            "计数":numpy.size
        }).reset_index().sort(
            columns=["计数"],
            ascending=False
        );
        
"""
groupby(by = [分组列A,分组列B,...])[统计列A,统计列B,...].agg({统计列A别名:统计函数...)

    count(*) -->  size
    sum(*)   -->  sum
    avg(*)   -->  mean

reset_index() 重排index

"""

#把小部分的数据删除掉
segStat = segStat[segStat.计数>1]

#进行文本向量计算,
#           columns = 'filePath'
#  index = segment   计数
textVector = segStat.pivot_table(
    index='segment', 
    columns='filePath', 
    values='计数',
    fill_value=0
) 

"""
交叉计数函数
    pivot_table(vaules,index,columns,aggfunc,fill_value)  --> 返回透视表中的结果
        values:数据透视表中的值
        index:数据透视表中的行
        columns:数据透视表中的列
        aggfunc:统计函数
        fill_value:NA值的统一替换
"""

TF = textVector.as_matrix(); # 使用matrix类创建的是矩阵对象

#hanlder = lambda x:(numpy.log2(len(corpos)/(numpy.sum(x>0)+1)))
def hanlder(x): 
    return (numpy.log2(len(corpos)/(numpy.sum(x>0)+1))) 
# log2(文档总数/包含该词的文档书)

IDF = textVector.apply(hanlder).as_matrix();

TF_IDF = TF * IDF

TF_IDF_DF = pandas.DataFrame(TF_IDF) # 将矩阵转为为数据框

tag1s = []
tag2s = []
tag3s = []
tag4s = []
tag5s = []
for i in range(len(corpos)):
    tagis = textVector.index[TF_IDF_DF.loc[:,i].order(ascending=False)[:5].index] # 第一列倒叙前5个
    tag1s.append(tagis[0])
    tag2s.append(tagis[1])
    tag3s.append(tagis[2])
    tag4s.append(tagis[3])
    tag5s.append(tagis[4])
# 形成 文件路劲 文章内容 关键字
tagDF = pandas.DataFrame({'filePath':corpos.filePath, 'content':corpos.content, 'tag1':tag1s, 'tag2':tag2s, 'tag3':tag3s, 'tag4':tag4s, 'tag5':tag5s})    

相似文章推荐简介

【挖掘篇】:文本分析_第2张图片
Paste_Image.png
import os
import os.path
import codecs
import numpy
import pandas
import jieba

#创建语料库
corpos = pandas.DataFrame(columns=['filePath', 'content'])

for root, dirs, files in os.walk(
    "F:\\python 数据挖掘分析实战\\Data\\SogouC.mini\\Sample\\"
):
    for name in files:
        filePath = root + '\\' + name;
        f = codecs.open(filePath, 'r', 'utf-8')
        content = f.read()
        f.close()
        corpos.loc[len(corpos)] = [filePath, content.strip()];

#进行分词
filePaths = []
segments = []
for i in range(len(corpos)):
    filePath = corpos.loc[i].filePath
    segs = jieba.cut(corpos.loc[i].content)
    for seg in segs:
        if len(seg.strip())>1:
            filePaths.append(filePath);
            segments.append(seg);

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

#移除停用词
stopwords = pandas.read_csv(
    "F:\\python 数据挖掘分析实战\\Code\\StopwordsCN.txt", 
    encoding='utf8', 
    index_col=False,
    quoting=3,
    sep="\t"
)

segmentDF = segmentDF[~segmentDF.segment.isin(stopwords.stopword)]

#按文章进行词频统计
segStat = segmentDF.groupby(
            by=["filePath", "segment"]
        )["segment"].agg({
            "计数":numpy.size
        }).reset_index().sort(
            columns=["计数"],
            ascending=False
        );

segStat = segStat[segStat.计数>1]

#进行文本向量计算
textVector = segStat.pivot_table(
    index='segment', # 分词为索引
    columns='filePath', # 文章路径为观测
    values='计数', # 分词对应文章为索引
    fill_value=0
)

def cosineDist(col1, col2): 
    # 计算余弦相似度
    return numpy.sum(col1 * col2)/(
        numpy.sqrt(numpy.sum(numpy.power(col1, 2))) * 
        numpy.sqrt(numpy.sum(numpy.power(col2, 2)))
    ) 

distance_df = textVector.apply(
    lambda col1: textVector.apply(
        lambda col2: cosineDist(col1, col2)
    ) # 计算每列列对应的余弦相似度
)

for i in range(len(corpos)):
    tagis = distance_df.iloc[:,i].order(ascending=False)[1:6].index 
    print("与 " + distance_df.index[i] + " 相似的文章:")
    print("\n".join(tagis))
    print("\n")
# 获取前六列的前余弦相似度文章

自动摘要

【挖掘篇】:文本分析_第3张图片
Paste_Image.png
import os
import os.path
import codecs
import numpy
import pandas
import jieba

#创建语料库
corpos = pandas.DataFrame(columns=['filePath', 'content'])

for root, dirs, files in os.walk(
    "F:\\python 数据挖掘分析实战\\Data\\SogouC.mini\\Sample\\"
):
    for name in files:
        filePath = root + '\\' + name;
        f = codecs.open(filePath, 'r', 'utf-8')
        content = f.read()
        f.close()
        corpos.loc[len(corpos)] = [filePath, content.strip()];

#移除停用词
stopwords = pandas.read_csv(
    "F:\\python 数据挖掘分析实战\\Code\\StopwordsCN.txt", 
    encoding='utf8', 
    index_col=False,
    quoting=3,
    sep="\t"
)

def cosineDist(col1, col2): 
    return numpy.sum(col1 * col2)/(
        numpy.sqrt(numpy.sum(numpy.power(col1, 2))) * 
        numpy.sqrt(numpy.sum(numpy.power(col2, 2)))
    )

import re
"""
m = "
  以禁止女兵穿低腰裤
  已有120名女兵因违规被关禁闭
  据新华社电 以军日前正在开展一场“全方位作战行动”。这次作战的目标可不是巴勒斯坦,而是女兵的低腰裤。
  以军一位发言人7日说:“根据以色列国防军军纪,北方司令部决定实施更加严格的政策,使士兵的穿着符合纪律规定。”以色列女兵纷纷抱怨说,军装不能很好地展示她们的身材。为了追赶时尚潮流,这些女兵们经常重新设计自己的军装,有些人甚至把它们改成了低腰裤。然而,女兵们爱美的天性并没有获得军队指挥官的同情,他们认为,低腰裤严重威胁着以军的纪律基础。
  以军要求女兵们把那些改过的低腰裤交到军需商店,以换回符合规定的军裤。此外,目前已经约有120名女兵因穿着违规低腰裤而被关禁闭。
n = [m] + re.split(r'[。?!\n]\s*', m)  
"""

#进行分词,一篇篇文章打印出来
for i in range(len(corpos)):
    #i = 0
    filePath = corpos.loc[i].filePath # 第i行第filePath列
    #建立子语料库,以该文档和该文档的分句组成
    subCorpos = [corpos.loc[i].content] + re.split(r'[。?!\n]\s*', corpos.loc[i].content) # 列表+列表
    # 内容+通过将第I行的内容将(.?!)分割为列表
    sub = []
    segments = []
    
    for j in range(len(subCorpos)):
        segs = jieba.cut(subCorpos[j])
        for seg in segs:
            if len(seg.strip())>1:
                sub.append(subCorpos[j]);
                segments.append(seg);
    # 文章,分句,分词
    segmentDF = pandas.DataFrame({'sub':sub, 'segment':segments})        

    segmentDF = segmentDF[~segmentDF.segment.isin(stopwords.stopword)]

    #按文章进行词频统计   group by 列,分词数--》计数
    segStat = segmentDF.groupby(
                by=["sub", "segment"]
            )["segment"].agg({
                "计数":numpy.size
            }).reset_index().sort(
                columns=["计数"],
                ascending=False
            );
    
    #进行文本向量计算
    textVector = segStat.pivot_table(
        index='segment', # 分词为索引
        columns='sub', # 句子为列/观测
        values='计数', # 分词在句子之间出现的次数
        fill_value=0
    )
    # 计算距离,apply(numpy.sum) 按列相加
    target = textVector.ix[:, textVector.apply(numpy.sum)==textVector.apply(numpy.sum).max()] 
    # 按列相加,最大的列,就是内容列
    textVector = textVector.ix[:, textVector.apply(numpy.sum)!=textVector.apply(numpy.sum).max()]
    # 这就是分句列
    distance = textVector.apply(lambda col: cosineDist(target.ix[:, 0], col)) 
    # 计算分句列和内容列之间的余弦相似度
    
    tagis = distance.order(ascending=False)[0:1].index # 找预先相似度最大的列
    print(corpos.loc[i].content) # 因为是循环的关系,可以形成一一对应的关系
    print(filePath + " 的摘要是:") 
    print(tagis) # ok

参考文献
作者A:ken

你可能感兴趣的:(【挖掘篇】:文本分析)