LoginSignup
2
2

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-09-18

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

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

ノック状況

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情報を抜き出して抜き出した文字列の先頭と語尾に'の'が来ないものを抽出したんですが、お題を正しく見たせていなかった。そして現コードへ修正。お題はちゃんと確認しないとダメですね。反省。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2