言語処理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()
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()
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()