Firebaseの技術情報サイト

Firebaseの技術情報サイト

Firebase活用の為の技術情報サイトです

日本語の文章から単語の出現回数を調べる

日本語の文章から単語の出現回数を調べる

前回の続きです。前回の投稿で、MeCab の設定でビルドをする方法を書きましたが、記事を読まれた方から pip で全てインストールできるというご指摘をいただきました。

ご指摘を受けて改めて、mecab-python 3のサイトを確認したところ、ご指摘の通り pip でインストールできることが書かれていました。ご指摘くださいましてどうもありがとうございます!

さて、MeCab の利用は、日本語の文章の単語の分割に利用しようというのが目的でしたので、そちらの話を進めていこうと思います。

単語に分けるだけでは不十分!

実際に、MeCab で日本語の文章の単語を抽出すれば簡単にできると思っていましたが、それだけでは不十分という事がやってみたらわかってきました。

前回最後に実行結果の例として、Jupyter notebook の実行結果を載せました。考えてみれば当然なんですが、MeCab は助詞や句読点も抽出します。

目的は、文章で使われる単語の出現回数を調べることでした。実際に、相談された方の目的も、こうした単語の数には余り興味が無いようでした。

品詞を指定して抜き出せば十分

実際の、要望としては、文章から名詞の単語を抜き出せば十分目的を果たせそうでした。そう考えると、実際に抜き出した単語の文字列と、品詞の部分を条件にして抽出した単語を振り分ければ良いことになります。

そう考えると、まずは品詞をチェックして名刺のみを抜き出して、その上で、同じ単語かどうかを判別して出現回数を数えれば当初の目的は達成できます。

拡張性を考えると

上のような方法で、名詞の単語を抜き出してあとは、単語の出現回数を数えるプログラムを力技で書けば良いのですが、その方法だと将来の拡張性は余り無くなってしまします。拡張性を考えると、MeCab の出力結果をできるだけそのまま取り込んで、必要な情報の条件を設定して取り出す形にした方が、多少処理時間やメモリの使用量は増えますが便利です。

そこで、「単語」と「付加情報」に分けてデータを取り込んで、単語と付加情報が一致する単語の出現回数を全ての単語に関して数える方法で作成する事にしました。

この方法ならば、名詞のキーワード検索以外の情報が必要になった時に、条件を変えることで別の情報として抜き出す事も可能になります。

今回は、この方針でサンプルコードを書いてみました

import MeCab
def find(lists, item):
    for word in lists:
        if isMatch(word,item):
            return word
    return None
def getCounts(a):
    return a["counts"]
def isMatch(a,b):
    if (a["word"] == b["word"]):
        matched = True
        for i in range(len(a["info"])):
            if a["info"][i] != b["info"][i]:
                matched = False
                break
        if matched:
            return True
        else:
            return False
    else:
        return False
def mecab(contents, option):
    results = []
    tagger = MeCab.Tagger(option)
    parsed = tagger.parse(contents)
    words = parsed.split('\n')
    for word in words:
        temp = word.split('\t')
        if len(temp) == 2:
            item = {"word":temp[0],"info":temp[1].split(','),"counts": 1}
            results.append(item)
    return results
def readFile(file):
    f = open(file,"r")
    contents = f.read()
    return contents

source = readFile("test.txt")
option = '-d /usr/local/lib/mecab/dic/mecab-ipadic-neologd'
words = []
print("入力した文章:",source)
results = mecab(source, option)
print("===== 結果 =====")
for result in results:
    found = find(words, result)
    if found == None:
        words.append(result)
    else:
        found["counts"] = found["counts"] + 1
words.sort(reverse=True, key=getCounts)
for word in words:
    if word["info"][0] == "名詞":
        print(word["word"],word["counts"])

取り敢えず、MeCab の出力は全て取り込んで、最後に名詞の出現回数を出力するようにしています。サンプルのコードではハードコードで名詞を抜き出すようにしていますが、この部分は後から変えられるようにすれば他の用途でも使えます。

対話的に実行が可能な jupyter notebook を利用して Python のプログラムを実行しているので書き換えて実行するのも簡単です。

昨日の記事の冒頭部分をサンプルにして実行した結果はこんな感じです。

先日、日本語の文章で使われる単語の傾向を調べたいという話をいただきました。 英語の場合は、単語と単語の間に必ずスペースがあるので、簡単なプログラムで単語を抜き出すことができます。しかし、日本語の場合は単語と単語の切れ目は日本語の文法を考慮しないと難しくなります。
そこで、インターネットで検索したところ、単語の抽出をやってくれるパッケージがある事がわかりました。幾つか公開されているパッケージがある様でしたが、「MeCab」というバッケージがよく利用されている様なので、試してました。
この記事では、簡単に MeCab について調べたことをまとめてみました。

===== 結果 =====
単語 7
日本語 3
場合 2
簡単 2
こと 2
パッケージ 2
様 2
MeCab 2
先日 1
文章 1
傾向 1
話 1
英語 1
間 1
スペース 1
プログラム 1

MeCab の情報部分をどこまで比較するかは、もう少し検討する必要があります。おそらく、最初の2つの要素を見れば良さそうな感じです。

細かい所は、さらに考える必要はありそうですが文章中の名詞の出現回数という当初の目的は一応達成できました。

まとめ

MeCab を利用すれば、日本語の文章中の名詞の出現回数などを数えることは簡単に実現できます。実際は、単純に単語を抽出するだけではなく、必要な種類の単語を抜き出すようなことを考える必要があります。

ただし、この情報をどうやって利用するかはもう少し考える必要がありそうです。今回は、書き手の好きな言葉や、癖を推測するのが主な目的だったので一応の目的は達成できました。しかし、もう少し考えると、さらに有効な利用方法がありそうだと言えます。

MeCab のような機能を自分で最初から作るのは大変ですが、このような便利なプログラムが公開されているので、これをどのように利用していくかをもう少し考えるとさらに面白い利用方法が見つかると思います。