【挖掘篇】:文本分析

# 词频统计(某一个给定的词在该文档中出现次数)
    # 语料库         分析的所有文档的集合
    # 中文分词       一个汉字序列切分成一个个单词
    # 停用词         数据处理的时候,自动过滤掉的某些字或词,包括泛滥的词,如: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()

关键词提取

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})    

相似文章推荐简介

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")
# 获取前六列的前余弦相似度文章

自动摘要

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容

  • 常用概念: 自然语言处理(NLP) 数据挖掘 推荐算法 用户画像 知识图谱 信息检索 文本分类 常用技术: 词级别...
    御风之星阅读 9,152评论 1 25
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,506评论 25 707
  • 词频统计 - 语料库的构建 遍历路径下的所有文件和子目录 os.walk() 读取目录及其所有子目录 root —...
    WesleyLien阅读 1,691评论 0 3
  • 程序员大部分的时间都是在和代码打交道,因此,对于文本编辑器一定不会陌生了。编辑器是处理文本的工具。 就像趁手的兵器...
    何幻阅读 957评论 0 7
  • 鬼金阅读 98评论 0 0