一,项目简介:

利用networkx官方中的CircularTree案例,修改节点的名称,利用唐代诗人姓名与其诗作中的关键字生成的边,形成以诗人关键字为代表的三层环形树状图。

附上原官方的CircularTree图,以及官方代码的链接。

https://networkx.github.io/documentation/stable/auto_examples/drawing/plot_circular_tree.html#sphx-glr-auto-examples-drawing-plot-circular-tree-py

python中matplotlib构建树形图 python 树形图_ci


二,实现方法:

1,从全唐诗文本中提取指定诗人的作品,我找到的版本标题含有中文【】,对于处理标题相当有利。

2,逐字解析指定诗人作品中的字,并按出现频率的高低排序,提取出现频率最高的m个字作为关键字(关键字不宜太多);

3,使用关键字搜索指定诗人的作品,将关键字前后的字+关键字组成的词语提取出来,形成列表,并按出现的频率排序,提取m个;

4,将m个关键字与m*m个词语组合成元组,形成networkx中的边;

5,引入networkx画关系图,使用balanced_tree和graphviz_layout组合形成节点名称+位置的字典,替换节点名称为诗人名称+关键字+词语的节点列表;

6,生成圆形树状图。

三,使用到的内置库和第三方库

1,collections中的Counter,用来统计列表中字和词语的个数,生成一个由字词语为键,出现的频率为值的字典;

2,re库,统计关键字在文本中出现的位置k,为提取(k-1)+k和k+(k+1)做必要的准备;

3,networkx中的balanced_tree生成指定的节点,graphviz_layout生成节点信息;Graph和draw生成图形;

4,matplot.pyplot输出图形。

四,附上几张生成的效果,就放李杜白元的作品吧,毕竟他们的作品在全唐诗中出现的比例也是最高的。

python中matplotlib构建树形图 python 树形图_ci_02


python中matplotlib构建树形图 python 树形图_字符串_03


python中matplotlib构建树形图 python 树形图_Graph_04


python中matplotlib构建树形图 python 树形图_字符串_05


五,附上源代码。

from collections import Counter
import re
import networkx as nx
import matplotlib.pyplot as plt
def getTxtByWriter(fn,writer,stopword,n):#获取全唐诗中指定作者的诗
    fo=open(fn,'r',encoding='utf-8-sig').readlines()
    peomWithWriter=''#诗的内容+作者标题
    for i in fo:
        if '【' in i:
            i=i.replace(i,'!'+i[i.find('【'):])#如果行有中文括号,表示此行为标题
            peomWithWriter+=(i.strip('\n'))
        else:
            peomWithWriter+=(i.strip('\n'))
    writerPoemWithIcon=''#诗的内容+标点符号
    for i in peomWithWriter.split('!'):#使用split分段开成列表
        if '】'+writer in i:#遍历列表是否有作者名称,有的话加入作者诗的字符串集
            i=i.split('】')[1]
            writerPoemWithIcon+=i.replace(writer,'')#replace(',','').replace('。','').replace(' ','')
    return writerPoemWithIcon

def getKeyWord(fn,writer,stopword,n):#获取出现频率最高的字
    writerPoemWithIcon=getTxtByWriter(fn,writer,stopword,n)
    WordDict=Counter(list(writerPoemWithIcon))#将生成的字符串List成列表,并统计每个字出现的次数
    sw=open(stopword,'r',encoding='utf-8').read().split('.')
    keyWordList=[]#关键字列表
    for k,v in WordDict.items():
        if k not in sw and v>n:#如果元素不在stopword中且出现的次数超过n次,就可以加入列表中。
            keyWordList.append(k)
    return keyWordList

# print(getKeyWord('全唐诗.txt','杜甫','ChineseStopWord.txt',400))

def getConnectWord(fn,writer,stopword,n,m):#文本,作者,停用词,关键字出现的频率,前m个关键字
    keyWordList=getKeyWord(fn,writer,stopword,n)[:m]#获取前m个关键字
    writerPoemWithIcon=getTxtByWriter(fn,writer,stopword,n)
    connectWordList=[]
    kwl=[]
    a=[writer]+keyWordList
    wk=[]
    for i in keyWordList:
        wk.append((writer,i))
        singleWord=[]
        list=[j.start() for j in re.finditer(i,writerPoemWithIcon)]#list是关键字i出现位置的列表
        for k in list:
            if writerPoemWithIcon[k+1] not in ',。 ' and writerPoemWithIcon[k-1] not in ',。 ':
                singleWord.append(writerPoemWithIcon[k:k+2])
                singleWord.append(writerPoemWithIcon[k-1:k+1])
        connectWord=[]
        kw=[]

        for k,v in sorted(Counter(singleWord).items(),key= lambda x:x[1],reverse=True):#关键字关联词的前m个
            connectWord.append((i,k))
            kw.append(k)
        connectWordList+=connectWord[:m]
        kwl=kwl+kw[:m]
    return wk+connectWordList,a+kwl

# print(getConnectWord('全唐诗.txt','杜甫','ChineseStopWord.txt',400,6))

def createCircularTree(fn,writer,stopword,n,m):#生成树形分支图
    connectWordList, nodeList = getConnectWord(fn, writer, stopword, n,m)
    try:
        import pygraphviz
        from networkx.drawing.nx_agraph import graphviz_layout
    except ImportError:
        try:
            import pydot
            from networkx.drawing.nx_pydot import graphviz_layout
        except ImportError:
            raise ImportError("This example needs Graphviz and either "
                          "PyGraphviz or pydot")
    plt.figure(figsize=(10, 10),facecolor='blue')
    g=nx.Graph()
    pos=graphviz_layout(nx.balanced_tree(m,3),prog='twopi')
    g.add_edges_from(connectWordList)
    p=dict(zip(nodeList,pos.values()))
    d=dict(g.degree)
    nx.draw(g,p,with_labels=True,nodelist=d.keys(),node_size=[v*400 for v in d.values()],node_color=range(len(nodeList)),
            cmap=plt.cm.Blues,alpha=0.8)
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.savefig('%s诗的主要意象.png'% writer,dpi=100)