Python
Python3
Pycharm
言語処理100本ノック

【python】100本ノックにチャレンジ!(030〜034)

More than 1 year has passed since last update.

これまでの経緯などについて

最初の投稿を参照ください

ノック状況

9/24追加

第4章: 形態素解析

夏目漱石の小説『吾輩は猫である』の文章(neko.txt)をMeCabを使って形態素解析し,その結果をneko.txt.mecabというファイルに保存せよ.このファイルを用いて,以下の問に対応するプログラムを実装せよ.なお,問題37, 38, 39はmatplotlibもしくはGnuplotを用いるとよい.

30. 形態素解析結果の読み込み

形態素解析結果(neko.txt.mecab)を読み込むプログラムを実装せよ.
ただし,各形態素は表層形(surface),基本形(base),品詞(pos),品詞細分類1(pos1)をキーとする
マッピング型に格納し,1文を形態素(マッピング型)のリストとして表現せよ.
第4章の残りの問題では,ここで作ったプログラムを活用せよ.

準備:neko.txt.mecabの作成

file_analyze_mecab_030.py
from natto import MeCab
import codecs

def file_analyze_mecab(input_filename,output_filename):

    with codecs.open(input_filename,'r','utf-8') as f:
        text = f.read()

    m = MeCab.Tagger("mecabrc")
    wt = m.parse(text)

    with codecs.open(output_filename,'w','utf-8') as wf:
        wf.write(wt)

if __name__=="__main__":
    file_analyze_mecab('neko.txt','neko.txt.mecab')
result
一 名詞,数,*,*,*,*,一,イチ,イチ
  記号,空白,*,*,*,*, , , 
吾輩  名詞,代名詞,一般,*,*,*,吾輩,ワガハイ,ワガハイ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
(長いので略)

感想:形態素解析って初めて聞いたので、そこから調査。mecabのパラメータなどはMeCab: Yet Another Part-of-Speech and Morphological Analyzerを参考にしました。モジュールなどのネーミングが素敵です。

030.読み込み

mecab_030.py
#-*-coding:utf-8-*-

import codecs

if __name__ == "__main__":
    with codecs.open("neko.txt.mecab",'r','utf-8') as f:
        data = f.readlines()

    mecab_list=[]
    temp_dict ={}
    for temp_word in data:
        temp_word = temp_word.replace('\t', ',')
        temp_word = temp_word.replace('\n', '')
        if(temp_word.count(',')==9 or temp_word.count(',')==7):
            temp_list = temp_word.split(',')
            temp_dict={'surface':temp_list[0],'base':temp_list[7],'pos':temp_list[1],'pos1':temp_list[2]}
            mecab_list.append(temp_dict)
        else:
            continue
    print(mecab_list)

    with codecs.open('neko.txt.mecab.analyze','w','utf-8') as wf:
        for line in mecab_list:
            wf.write(str(line)+'\n')
result
{'surface': '物', 'base': '物', 'pos': '名詞', 'pos1': '一般'}
(長いので略)

感想:出力するファイルは見やすいようにリスト型ではなく、ただの文字列に置き換えました。形態素解析の結果の列に含まれる','の数が7だったり9だったりということに気づくまでとてもハマりました。。。

031. 動詞

動詞の表層形をすべて抽出せよ.

vurb_031.py
#-*-coding:utf-8-*-

import codecs
import re
import ast

if __name__ == "__main__":
    with codecs.open("neko.txt.mecab.analyze",'r','utf-8') as f:
        temp_lines = f.readlines()

    pattern = re.compile(r".*動詞.*")
    data = {}
    for temp_line in temp_lines:
        if pattern.match(temp_line):
            data = ast.literal_eval(temp_line)
            print(data['surface'])
        else:
            continue
result
で
ある
生れ
た
つか
(長いので略)

感想:解析結果のファイルを読み込み、動詞というキーワードを持った列を正規表現で抜き出して、辞書型へ変換後surfaceだけ出力してる。

032. 動詞の原形

動詞の原形をすべて抽出せよ.

base_vurb_032.py
# -*-coding:utf-8-*-

import codecs
import re
import ast

if __name__ == "__main__":
    with codecs.open("neko.txt.mecab.analyze", 'r', 'utf-8') as f:
        temp_lines = f.readlines()

    pattern = re.compile(r".*動詞.*")
    data = {}
    for temp_line in temp_lines:
        if pattern.match(temp_line):
            data = ast.literal_eval(temp_line)
            print(data['base'])
        else:
            continue
result
だ
ある
生れる
た
つく

感想:手順は031と同じ。出力をbaseに変えている。

033. サ変名詞

サ変接続の名詞をすべて抽出せよ.

sahen_noun_033.py
# -*-coding:utf-8-*-

import codecs
import re
import ast

if __name__ == "__main__":
    with codecs.open("neko.txt.mecab.analyze", 'r', 'utf-8') as f:
        temp_lines = f.readlines()

    pattern = re.compile(r".*サ変接続.*")
    data = {}
    for temp_line in temp_lines:
        if pattern.match(temp_line):
            data = ast.literal_eval(temp_line)
            print(data['surface'])
        else:
            continue
result
見当
記憶
話
装飾
突起
(長いので略)

感想:手順は032と同じ。抽出する条件をサ変接続へ変えただけ。

034. 「AのB」

2つの名詞が「の」で連結されている名詞句を抽出せよ.

no_noun_034.py
#-*-coding:utf-8-*-

import codecs
import ast

if __name__ == "__main__":

    with codecs.open('neko.txt.mecab.analyze','r','utf-8') as f:
        temp_lines = f.readlines()

    flag = 0
    temp_list = []
    for temp_line in temp_lines:
        temp_dict = ast.literal_eval(temp_line)
        if (temp_dict['pos'] == '名詞' and flag == 0):
            temp_word = temp_dict['surface']
            flag = 1
            continue

        elif(temp_dict['surface']=='の' and temp_dict['pos']=='助詞' and flag == 1):
            temp_word += temp_dict['surface']
            flag = 2
            continue

        elif(temp_dict['pos']=='名詞' and flag == 2):
            temp_word += temp_dict['surface']
            temp_list.append(temp_word)
            temp_word = ''
            flag = 0
            continue

        else:
            temp_word=''
            flag =0
            continue

    no_noun_list = set(temp_list)


    for temp in no_noun_list:
        print(temp)
result
者の子
自分の年
無聊のあまり
左の隅
相手の力量
額の上
方のため
(長いので略)

感想:最初にN=3でposの情報をngram解析して名詞助詞名詞の並びになっているindex番号をリスト化して、その後にマッチするindex番号のsurface情報を抜き出して抜き出した文字列の先頭と語尾に'の'が来ないものを抽出したんですが、お題を正しく見たせていなかった。そして現コードへ修正。お題はちゃんと確認しないとダメですね。反省。