個人的神殿

プログラミング

言語処理100本ノック 第4章

30.
Mecabにはほとんど触ったことが無かったが、とにかく見様見真似でやってみる。
ちなみに最初while文の中でnode = node.nextを書き忘れて無限ループに陥り、PCがフリーズしてしまったので再起動した。

import MeCab
def map_text(text_file):
    with open(text_file, encoding = "utf-8") as fp:
        sentences = []
        lines = fp.readlines() # list
        tagger = MeCab.Tagger("-O chasen")
        tagger.parse('')

        for line in lines:
            sentence = []
            node = tagger.parseToNode(line.replace("\n", "").replace(" ", ""))

            while node:
                if node.surface == "":
                    node = node.next
                    continue

                surface = node.surface
                base = node.feature.split(",")[6]
                pos = node.feature.split(",")[0]
                pos1 = node.feature.split(",")[1]

                word = {
                    "surface": surface,
                    "base": base,
                    "pos": pos,
                    "pos1": pos1
                }

                sentence.append(word)
                node = node.next

            if sentence:
                sentences.append(sentence)
        
        return sentences

def create_result_file(text_file):
    sentences = map_text(text_file)
    with open("neko.txt.mecab", "w", encoding = "utf-8") as result_file:
        for sentence in sentences:
            result_file.write(str(sentence) + "\n")

create_result_file("neko.txt")
[{'surface': '一', 'base': '一', 'pos': '名詞', 'pos1': '数'}]
[{'surface': '吾輩', 'base': '吾輩', 'pos': '名詞', 'pos1': '代名詞'}, {'surface': 'は', 'base': 'は', 'pos': '助詞', 'pos1': '係助詞'}, {'surface': '猫', 'base': '猫', 'pos': '名詞', 'pos1': '一般'}, {'surface': 'で', 'base': 'だ', 'pos': '助動詞', 'pos1': '*'}, {'surface': 'ある', 'base': 'ある', 'pos': '助動詞', 'pos1': '*'}, {'surface': '。', 'base': '。', 'pos': '記号', 'pos1': '句点'}]
[{'surface': '名前', 'base': '名前', 'pos': '名詞', 'pos1': '一般'}, {'surface': 'は', 'base': 'は', 'pos': '助詞', 'pos1': '係助詞'}, {'surface': 'まだ', 'base': 'まだ', 'pos': '副詞', 'pos1': '助詞類接続'}, {'surface': '無い', 'base': '無い', 'pos': '形容詞', 'pos1': '自立'}, {'surface': '。', 'base': '。', 'pos': '記号', 'pos1': '句点'}]
[{'surface': 'どこ', 'base': 'どこ', 'pos': '名詞', 'pos1': '代名詞'}, {'surface': 'で', 'base': 'で', 'pos': '助詞', 'pos1': '格助詞'}, {'surface': '生れ', 'base': '生れる', 'pos': '動詞', 'pos1': '自立'}, {'surface': 'た', 'base': 'た', 'pos': '助動詞', 'pos1': '*'}, {'surface': 'か', 'base': 'か', 'pos': '助詞', 'pos1': '副助詞/並立助詞/終助詞'}, {'surface': 'とんと', 'base': 'とんと', 'pos': '副詞', 'pos1': '一般'}, {'surface': '見当', 'base': '見当', 'pos': '名詞', 'pos1': 'サ変接続'}, {'surface': 'が', 'base': 'が', 'pos': '助詞', 'pos1': '格助詞'}, {'surface': 'つか', 'base': 'つく', 'pos': '動詞', 'pos1': '自立'}, {'surface': 'ぬ', 'base': 'ぬ', 'pos': '助動詞', 'pos1': '*'}, {'surface': '。', 'base': '。', 'pos': '記号', 'pos1': '句点'}]

31.
重複するかもしれないので集合で。

sentences = map_text("neko2.txt")
print({word["surface"] for sentence in sentences for word in sentence if word["pos"] == "動詞" })
{'あっ', '逢っ', '見', 'なら', 'いる', '思わ', '煮', '落ちつい', '捕え', '出会わ', '弱っ', 'のみ', 'さ', '思っ', 'られ
', 'れ', '吹く', 'つか', '載せ', '聞く', 'し', '食う', '残っ', 'せ', '飲む', '生れ', '持ち上げ', '知っ', '泣い', '始め
', ……}

32.

print({word["base"] for sentence in sentences for word in sentence if word["pos"] == "動詞"})

33.

print({word["surface"] for sentence in sentences for word in sentence if word["pos"] == "名詞" and word["pos1"] == "サ変接続"})

34.
名詞と名詞をつなぐ「の」の働きは連体化というらしい。
確かにその前後の単語は名詞になっている。
はずってたしかに名詞なんだがあまり名詞って感じがしないね。

for sentence in sentences:
    for i, word in enumerate(sentence):
        if word["pos1"] == "連体化":
            print(sentence[i - 1]["surface"] + "の" + sentence[i + 1]["surface"])
彼の掌
掌の上
書生の顔
はずの顔
顔の真中
穴の中

35.
ぷうぷうと とか ニャーニャーって名詞だったんだ(笑)

nouns_list = []

for sentence in sentences:
    nouns = []
    for word in sentence:
        if word["pos"] == "名詞":
            nouns.append(word["surface"])
        elif word["pos"] != "名詞" and nouns != []:
            nouns_list.append(nouns)
            nouns = []
nouns_list = sorted(nouns_list, key = lambda x: len(x), reverse = True)
print(nouns_list)
[['人間', '中'], ['一番', '獰悪'], ['時', '妙'], ['一', '毛'], ['その後', '猫'], ['一', '度'], ['ぷうぷうと', '煙'], ['吾輩'], ['猫'], ['名前'], ['どこ'], ['見当'], ['何'], ['所'], ['ニャーニャー'], ['いた事'], ['記憶'], ['吾輩'], ['ここ'], ['人間'], ['もの'], ['あと'], ['それ'], ['書生'], ['種族'], ['そう'], ['書生'], ['の'], ['我々'], ['話'], ['当時'], ['何'], ['考'], ['彼'], ['掌'], ['スー'], ['時'], ['感じ'], ['掌'], ['上'], ['書生'], ['顔'], ['の'], ['人間'], ['もの'], ['始'], ['もの'], ['感じ'], ['今'], ['装飾'], ['はず'], ['顔'], ['薬缶'], ['輪'], ['事'], ['顔'], ['真中'], ['突起'], ['穴'], ['中'], ['咽'], ['これ'], ['人間'], ['煙草'], ['もの'], ['事'], ['頃']]

36.
まぁ、助詞なども一応単語だから……。
それと第2章で学んだdefaultdictをここでも使ってみた。

from collections import defaultdict

word_nums = defaultdict(int)
for sentence in sentences:
    for word in sentence:
        if word["pos"] != "記号":
            word_nums[word["surface"]] += 1
word_nums = sorted(word_nums.items(), key = lambda x: x[1], reverse = True)
print(word_nums[:10])
[('た', 15), ('で', 12), ('て', 11), ('の', 10), ('は', 9), ('が', 9), ('という', 7), ('し', 6), ('ある', 4), ('人間', 4)]

37.
初めてmatplotlibを触った。
棒グラフを出すこと自体は難しくなかったが、文字化けがなかなか直らなかった。
結果的にこちらのサイトに通りにしたら直った。
tkstock.site

棒グラフはbarを使う。

from matplotlib import pyplot

x = [word[0] for word in word_nums[:10]]
y = [word[1] for word in word_nums[:10]]

pyplot.bar(x, y, label = "word_num_ranking")

pyplot.title("頻度上位10語")
pyplot.xlabel("単語")
pyplot.ylabel("出現数")
pyplot.show()

f:id:beyonce_t:20191021220542j:plain
頻度上位10単語

38.
ヒストグラムはhistを使う。第1引数にデータ、binsは棒の数、rangeは横軸の範囲。

from matplotlib import pyplot

pyplot.hist([word_num[1] for word_num in word_nums], bins = 30, range = (1, 30))
pyplot.title("種類別頻度")
pyplot.xlabel("出現頻度")
pyplot.ylabel("出現数")
pyplot.show()

f:id:beyonce_t:20191021223337j:plain
種類別頻度

39.

xscaleとyscaleにlogをセットすると、軸をlogスケールで描くことができるらしい。
from matplotlib import pyplot

y = [word_num[1] for word_num in word_nums]
x = list(range(1, len(y) + 1))

pyplot.plot(x, y)

pyplot.xscale('log')
pyplot.yscale('log')

pyplot.title("出現頻度順位")
pyplot.xlabel("出現頻度順位")
pyplot.ylabel("出現頻度")
pyplot.show()

f:id:beyonce_t:20191021230306j:plain
出現頻度順位