言語処理100本ノック 2015「第4章: 形態素解析」の35本目「名詞の連接」記録です。
前回と同様、pandasで簡単に処理できないない内容です。ですが、「名詞の連接」部分は10行程度の難しくはない処理です。
参考リンク
リンク | 備考 |
---|---|
035.名詞の連接.ipynb | 回答プログラムのGitHubリンク |
素人の言語処理100本ノック:35 | 多くのソース部分のコピペ元 |
MeCab公式 | 最初に見ておくMeCabのページ |
環境
種類 | バージョン | 内容 |
---|---|---|
OS | Ubuntu18.04.01 LTS | 仮想で動かしています |
pyenv | 1.2.16 | 複数Python環境を使うことがあるのでpyenv使っています |
Python | 3.8.1 | pyenv上でpython3.8.1を使っています パッケージはvenvを使って管理しています |
Mecab | 0.996-5 | apt-getでインストール |
上記環境で、以下のPython追加パッケージを使っています。通常のpipでインストールするだけです。
種類 | バージョン |
---|---|
pandas | 1.0.1 |
第4章: 形態素解析
学習内容
夏目漱石の小説『吾輩は猫である』に形態素解析器MeCabを適用し,小説中の単語の統計を求めます.
形態素解析, MeCab, 品詞, 出現頻度, Zipfの法則, matplotlib, Gnuplot
ノック内容
夏目漱石の小説『吾輩は猫である』の文章(neko.txt)をMeCabを使って形態素解析し,その結果をneko.txt.mecabというファイルに保存せよ.このファイルを用いて,以下の問に対応するプログラムを実装せよ.
なお,問題37, 38, 39はmatplotlibもしくはGnuplotを用いるとよい.
35. 名詞の連接
名詞の連接(連続して出現する名詞)を最長一致で抽出せよ.
課題補足(「」について)
回答
回答プログラム 035.名詞の連接.ipynb
import pandas as pd
def read_text():
# 0:表層形(surface)
# 1:品詞(pos)
# 2:品詞細分類1(pos1)
# 7:基本形(base)
df = pd.read_table('./neko.txt.mecab', sep='\t|,', header=None,
usecols=[0, 1, 2, 7], names=['surface', 'pos', 'pos1', 'base'],
skiprows=4, skipfooter=1 ,engine='python')
return df[df['pos'] == '名詞']
df = read_text()
nouns = []
for index in df['surface'].index:
nouns.append(df['surface'][index])
# ひとつ先のインデックスがない場合は名詞連接の終端
if (index + 1) not in df.index:
# 複数(連接)の場合
if len(nouns) > 1:
print(len(nouns), '\t', index, '\t', ''.join(nouns))
nouns = []
# 多いので制限
if index > 2000:
break
回答解説
ファイル読込
今回は名詞以外は不要なのでファイル読込直後に名詞だけを対象にエントリを絞っています。
def read_text():
# 0:表層形(surface)
# 1:品詞(pos)
# 2:品詞細分類1(pos1)
# 7:基本形(base)
df = pd.read_table('./neko.txt.mecab', sep='\t|,', header=None,
usecols=[0, 1, 2, 7], names=['surface', 'pos', 'pos1', 'base'],
skiprows=4, skipfooter=1 ,engine='python')
return df[df['pos'] == '名詞']
名詞連接抽出
あとはループでの処理です。次エントリのインデックスが+1かどうかで連接終端判断をしています。連接終端で連接リストの長さが1以上の場合のみ名詞連接を出力します。
nouns = []
for index in df['surface'].index:
nouns.append(df['surface'][index])
# ひとつ先のインデックスがない場合は名詞連接の終端
if (index + 1) not in df.index:
# 複数(連接)の場合
if len(nouns) > 1:
print(len(nouns), '\t', index, '\t', ''.join(nouns))
nouns = []
出力結果(実行結果)
プログラム実行すると以下の結果が出力されます。
2 28 した所
2 66 人間中
2 69 一番獰悪
2 172 時妙
2 190 一毛
2 209 その後猫
2 222 一度
2 688 邸内
2 860 書生以外
3 1001 四五遍
2 1028 この間おさん
2 1031 三馬
2 1106 御台所
2 1150 まま奥
2 1235 終日書斎
2 1255 勉強家
2 1266 勉強家
2 1288 勤勉家
3 1392 二三ページ
2 1515 主人以外
2 1581 限り吾輩
2 1599 朝主人
2 1690 一番心持
2 1733 一つ床
2 1781 最後大変
3 1829 神経胃弱性
2 1913 言語同断
2 1961 しようもの
3 1965 家内総がかり