見出し画像

文章のWordCloudと共起ネットワークを作成するPythonコード

これから記事制作の一環として文章を自然言語処理で解析→視覚化して分かりやすくする、という工程を入れたいと考え自分用のメモも兼ねWordCloud・共起ネットワークの作り方をまとまったコードにして見ました。

WordCould

形態素解析にMecabを、例文にWikipediaのソクラテスの記事を使ってます。
実行環境は最新版のAnaconda + JupyterNotebookです。

import MeCab
from glob import glob

 #WordCloud #文書を読み込み・邪魔になる記号を除去
filepaths = glob('socrates.txt')
filepaths
filepaths = filepaths[0]
with open(filepaths, "r", encoding="utf8") as f: 
    txt = f.read().replace('\u3000', '')
    
#WordCouldを作成 - Mecabで形態素解析し、名詞のみを抽出する
wc = WordCloud( width =1920, height = 1080, font_path = font_path)
mecab = MeCab.Tagger()
nodes = mecab.parseToNode(txt)
s = []

while nodes:
    if nodes.feature[:2] == '名詞':
        s.append(nodes.surface)
    nodes = nodes.next

#ストップワードを設定 → ストップワードを除去してWordCloudを出力
stopwords = {"もの","これ","ため","それ","ところ","よう","こと"}
wc = WordCloud(width =1920, height = 1080, stopwords=stopwords, font_path = font_path, colormap = "PuBu")

wc.generate(" ".join(s))
wc.to_file('socrates_jp02.png')
plt.imshow(wc)

弟子の名前や「ソフィスト」という彼の通称、無知・対話といったソクラテスっぽい用語が組み込まれています。ただ彼の哲学ではなく歴史的経緯の記述が多い関係か、この図からソクラテスの学説や人物像を想像するのはちょっと難しいですね。

共起ネットワーク

 #共起ネットワーク from pathlib import Path
import re
import collections
import pandas as pd
import MeCab
import mojimoji
import neologdn
import unicodedata
import itertools
import networkx as nx
import matplotlib.pyplot as plt
import ipadic

CHASEN_ARGS = r' -F "%m\t%f[7]\t%f[6]\t%F-[0,1,2,3]\t%f[4]\t%f[5]\n"'
CHASEN_ARGS += r' -U "%m\t%m\t%m\t%F-[0,1,2,3]\t\t\n"'
tagger = MeCab.Tagger(ipadic.MECAB_ARGS + CHASEN_ARGS)
#}txt_parsed = print(tagger.parse(txt)[:-4])

while nodes:
    if nodes.feature[:2] == '名詞':
        s.append(nodes.surface)
    nodes = nodes.next
    
#print(s)

def get_noun_words_from_sentence(sentence, mecab, stopword_list=[]):
    return [x.split('\t')[0] for x in mecab.parse(sentence).split('\n') if len(x.split('\t')) > 1 and \
         "名詞"in x.split('\t')[3] and x.split('\t')[0] not in stopword_list]


def split_sentence(sentence, mecab, stopword_list):
    sentence = neologdn.normalize(sentence)
    sentence = unicodedata.normalize("NFKC", sentence)
    words = get_noun_words_from_sentence(
        sentence=sentence, mecab=mecab, stopword_list=stopword_list
    )
    words = list(map(lambda x: re.sub(r'\d+\.*\d*', '0', x.lower()), words))
    return words

noun_sentences = []
stopword_list = {"もの","これ","ため","それ","ところ","よう","こと","ん","の","さ"}

for sentence in sentence_list:
    noun_sentences.append(split_sentence(sentence=sentence, mecab=tagger, stopword_list=stopword_list))

#for words in noun_sentences:
    #print(words)
    
df = pd.DataFrame( sentence_list,columns=["text"])
#df.head(10)
def mecab_text(text):

    mecab = MeCab.Tagger()
    node = mecab.parseToNode(text)
    wordlist = []
    
    while node:
        
        #名詞のみリストに格納する
        if node.feature.split(',')[0] == '名詞':
            wordlist.append(node.surface)
            
        #他の品詞を取得したければ、elifで追加
        elif node.feature.split(',')[0] == '代名詞':
            wordlist.append(node.surface)
        elif node.feature.split(',')[0] == '形容詞':
            wordlist.append(node.surface)
        #elif node.feature.split(',')[0] == '動詞':
            #wordlist.append(node.surface)
            
        node = node.next
    return wordlist

#形態素結果をリスト化し、データフレームdf1に結果を列追加する
df['words'] = df['text'].apply(mecab_text)

#表示
#df

import nlplot

npt = nlplot.NLPlot(df, target_col='words')

# top_nで頻出上位単語, min_freqで頻出下位単語を指定できる
#stopwords = npt.get_stopword(top_n=0, min_freq=0)
stopwords = ["もの","それ","なく","ため","これ","こと"]

npt.bar_ngram(
    title='uni-gram',
    xaxis_label='word_count',
    yaxis_label='word',
    ngram=1,
    top_n=50,
    stopwords=stopwords,
)

# ビルド
npt.build_graph(stopwords=stopwords, min_edge_frequency=4)

display(
    npt.node_df.head(), npt.node_df.shape,
    npt.edge_df.head(), npt.edge_df.shape
)

npt.co_network(
    title='Co-occurrence network_soc' ,save=True
)


共起ネットワークを用いると記事内のソクラテスの人物像がより明らかになります。プラトンと近しい関係にある他、哲学というノードから彼が「賢者、無知、ソフィスト」等々であることが分かりますね。

次回は成果が出次第、自然言語分析について更に書いていく予定です。お楽しみに!

この記事が気に入ったらサポートをしてみませんか?