質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.49%

  • Python 3.x

    6431questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • pandas

    586questions

    Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

  • UTF-8

    109questions

    UTF-8は8ビット符号単位の文字符号化形式及び文字符号化スキームです。データ交換方式、ファイル形式としては、一般的にUTF-8が使われる傾向があります。

janomeによる形態素解析で、簡略辞書が結果に反映されません。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 193

SKIYO

score 4

janomeで形態素解析を行っています。

utf-8対応の文章に対して、
utf-8の簡略辞書(csvファイル)を同コード内で作成し、それを形態素解析に反映させたいのですが、
なぜか上手くいきません。
(実行時にエラーが出るわけではなく、t = Tokenizer() と同じ結果しか得られない。)

どうすれば簡略辞書が反映されるのか、ご教授いただけたら幸甚です。

バージョン
Python 3.6.5
Janome 0.3.6
pandas 0.23.1

以下、コードです。
(なお、プライバシーに関係しそうな箇所を---にしています。)

import pandas as pd
import codecs as cd
import numpy as np
import math
import re
import xlrd
import xlsxwriter
from collections import Counter
from itertools import chain
from janome.tokenizer import Tokenizer
import os
import csv



with cd.open(r"\\---\---.csv", "r", "utf-8") as file:
    df = pd.read_csv(file, index_col=0)

## 行drop
df.dropna(how='any', inplace=True)
#how='any':一つでもNaN(Not a Number)がある行/列(,axis=1)をdrop なお、how='all'は全てがNaNをdrop
#inplace=True:元のdfが変更される。

## 昇順ソート
df.sort_index(inplace=True) #axis=1:列方向にソート ascending=False:降順でソート by='列名':その列内の値がソート基準になる

## Create User dictionary in UTF-8
#http://akiyoko.hatenablog.jp/entry/2017/12/09/010411
def main():
    rows = [['展示会', 'カスタム名詞', 'テンジカイ'], ['中国市場', 'カスタム名詞', 'チュウゴクシジョウ'], ['可能性', 'カスタム名詞', 'カノウセイ']]
    with open('dict_simple_utf8.csv', 'w', newline='', encoding='utf-8-sig') as f:
        w = csv.writer(f, quoting=csv.QUOTE_ALL)
        w.writerows(rows)

if __name__ == '__main__':
    main()


## User dictionary
t = Tokenizer(r"dict_simple_utf8.csv", udic_type="simpledic", udic_enc="utf8")#Tokenizer初期化

data = []
each_data = []
c = 0
for i in range(len(df.index)):
    value = df.iat[i, 0] #.iat[行番号, 列番号] なお、.at['行ラベル', '列ラベル']も可能
    tokens = t.tokenize(value)
    for token in tokens:
        partOfSpeech = token.part_of_speech.split(',')[0] #.part_of_speech.split(',')[0]:品詞
        #なお、[1]~[3]は品詞細分類1~3
        #その他、.infl_type:活用型、.infl_form:活用形、.base_form:原形、.reading:読み、.phonetic:発音
        if partOfSpeech == u'名詞': #名詞を抽出する
            each_data.append(token.surface) #.surface:表層形(tokenそのもの)
    data.append(each_data)
    each_data = []
    c += 1
    if c == 2:
        break

##エクセル作成
#ファイル作成
output_Exl = xlsxwriter.Workbook(r"result_pd\morphology.xlsx")
#シート作成
output_sht = output_Exl.add_worksheet('tokens')


for row in range(len(data)):
    for i in range(len(data[row])):
        output_sht.write(row, i, data[row][i]) # (行, 列, 追加するデータ)


##data(リストのリスト)内のすべてのtokensを同じリストに格納
#print(chain.from_iterable(data)) #<itertools.chain object at 0x000001B42F87D748>
chain_data = list(chain.from_iterable(data)) #chain(.from_iterable)():iterableなオブジェクトを一つのオブジェクトにまとめる
#http://coolpythontips.blogspot.com/2016/02/itertoolschain.html

c = Counter(chain_data) #Counterは、keyに要素、valueに出現回数の、辞書型のサブクラス
result_ranking = c.most_common(100) #(要素, 出現回数)という形のタプルを出現回数が多い順に並べたリストを返す。引数にnを入力すると、上位n位までを対象にする。
#https://note.nkmk.me/python-collections-counter/

ranking = output_Exl.add_worksheet('count')
for row in range(len(result_ranking)):
    for i in range(len(result_ranking[row])):
        ranking.write(row, i, result_ranking[row][i])

output_Exl.close() #エクセル保存
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

簡略辞書フォーマット (v0.2.7 以上)を参考に

# -*- coding: utf-8 -*-
from janome.tokenizer import Tokenizer
import csv


def main():
    rows = [['展示会', 'カスタム名詞', 'テンジカイ'], ['中国市場', 'カスタム名詞', 'チュウゴクシジョウ'], ['可能性', 'カスタム名詞', 'カノウセイ']]
    with open('dict_simple_utf8.csv', 'w', newline='', encoding='utf-8-sig') as f:
        # quoting=csv.QUOTE_ALLを削除
        w = csv.writer(f)
        w.writerows(rows)

if __name__ == '__main__':
    main()

# udic_encをutf-8-sigに
t = Tokenizer(r"dict_simple_utf8.csv", udic_type="simpledic", udic_enc="utf-8-sig")
tokens = t.tokenize('展示会')
for token in tokens:
    print(token)


○出力結果

展示会    カスタム名詞,*,*,*,*,*,展示会,テンジカイ,テンジカイ


◇参考情報
tests#user_simpledic.csv

あと適度に関数分割されることをお勧め致します。


「udic_encをutf-8-sigに」したのは、簡略辞書のdict_simple_utf8.csvと、encodingを一緒にしなくてはならなかったからでしょうか。

はい、そうです。

関数化に関して

関数の分け方は一つの纏まり「入力→加工→出力」この形を一つとして分けると良いです。

質問文のコードが行っていることは、

  1. pandasを使って、csvの内容を読み取り。
  2. janome用のカスタム辞書を作成。
  3. 1で読み取った内容に対して、janomeで形態解析。
  4. エクセル作成

この4つの処理です。以下は書き換えたソースコードです、ご参考まで。

# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
import math
import re
import xlrd
import xlsxwriter
from collections import Counter
from itertools import chain
from janome.tokenizer import Tokenizer
import os
import csv


def create_user_dic_file(file_name: str='dict_simple_utf8.csv', encoding: str='utf-8-sig'):
    """
    janomeのカスタム辞書を作成
    :param file_name 出力辞書ファイル名 csv形式
    :param encoding ファイルのエンコーディング形式
    ## Create User dictionary in UTF-8
    # http://akiyoko.hatenablog.jp/entry/2017/12/09/010411
    """
    rows = [['展示会', 'カスタム名詞', 'テンジカイ'], ['中国市場', 'カスタム名詞', 'チュウゴクシジョウ'], ['可能性', 'カスタム名詞', 'カノウセイ']]
    with open(file_name, 'w', newline='', encoding=encoding) as f:
        w = csv.writer(f)
        w.writerows(rows)


def read_data(file_name: str, encoding: str='utf-8'):
    """
    :param file_name 入力ファイル csv形式
    :param encoding ファイルのエンコーディング形式
    """
    # ※ openはencodingオプションでエンコード指定を行えるためcodecsを使用しないように変更
    with open(file_name, "r", encoding=encoding) as file:
        df = pd.read_csv(file, index_col=0)

    ## 行drop
    df.dropna(how='any', inplace=True)
    # how='any':一つでもNaN(Not a Number)がある行/列(,axis=1)をdrop なお、how='all'は全てがNaNをdrop
    # inplace=True:元のdfが変更される。

    ## 昇順ソート
    df.sort_index(inplace=True)  # axis=1:列方向にソート ascending=False:降順でソート by='列名':その列内の値がソート基準になる

    for i in range(len(df.index)):
        # ※ yieldを使う
        yield df.iat[i, 0]  # .iat[行番号, 列番号] なお、.at['行ラベル', '列ラベル']も可能


def parse(file_name: str):
    """
    :param file_name 入力ファイル csv形式
    """
    ## User dictionary
    t = Tokenizer(r"dict_simple_utf8.csv", udic_type="simpledic", udic_enc="utf-8-sig")  # Tokenizer初期化
    data = []
    each_data = []
    c = 0
    for value in read_data(file_name):
        for token in t.tokenize(value):
            partOfSpeech = token.part_of_speech.split(',')[0]  # .part_of_speech.split(',')[0]:品詞
            # なお、[1]~[3]は品詞細分類1~3
            # その他、.infl_type:活用型、.infl_form:活用形、.base_form:原形、.reading:読み、.phonetic:発音
            if partOfSpeech == u'名詞':  # 名詞を抽出する
                each_data.append(token.surface)  # .surface:表層形(tokenそのもの)
        data.append(each_data)
        each_data = []
        c += 1
        if c == 2:
            break
    return data


def create_excel(file_name: str, data=None):
    """
    エクセル作成
    :param file_name 出力ファイル名
    :data
    """
    from contextlib import closing
    # ※ contextlib#closingを使用
    # ファイル作成
    with closing(xlsxwriter.Workbook(file_name)) as output_Exl:
        # シート作成
        output_sht = output_Exl.add_worksheet('tokens')

        for row in range(len(data)):
            for i in range(len(data[row])):
                output_sht.write(row, i, data[row][i])  # (行, 列, 追加するデータ)

        ##data(リストのリスト)内のすべてのtokensを同じリストに格納
        # print(chain.from_iterable(data)) #<itertools.chain object at 0x000001B42F87D748>
        chain_data = list(chain.from_iterable(data))  # chain(.from_iterable)():iterableなオブジェクトを一つのオブジェクトにまとめる
        # http://coolpythontips.blogspot.com/2016/02/itertoolschain.html

        c = Counter(chain_data)  # Counterは、keyに要素、valueに出現回数の、辞書型のサブクラス
        result_ranking = c.most_common(100)  # (要素, 出現回数)という形のタプルを出現回数が多い順に並べたリストを返す。引数にnを入力すると、上位n位までを対象にする。
        # https://note.nkmk.me/python-collections-counter/

        ranking = output_Exl.add_worksheet('count')
        for row in range(len(result_ranking)):
            for i in range(len(result_ranking[row])):
                ranking.write(row, i, result_ranking[row][i])


def parse_args():
    """
        コマンドライン引数の解析
    """
    input_file = r"./input_csv.csv"
    from argparse import ArgumentParser
    parser = ArgumentParser()
    parser.add_argument('input_file', metavar=None, nargs='?', default=input_file)

    return parser.parse_args()


def main():
    args = parse_args()
    create_user_dic_file()
    data = parse(args.input_file)
    create_excel(r"result_pd\morphology.xlsx", data)


if __name__ == '__main__':
    main()

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/20 02:31

    回答ありがとうございます。
    無事に、簡略辞書を反映させることができました。

    なお、
    ①なぜ「quoting=csv.QUOTE_ALLを削除」したのかは、自分で調べるとして、

    ②「udic_encをutf-8-sigに」したのは、簡略辞書のdict_simple_utf8.csvと、encodingを一緒にしなくてはならなかったからでしょうか。

    また、
    ③「適度に関数化」するとは、たとえば私のコーディングに対して、umyuさんのような上級の方たちは、主にどこを、どのように関数化するのでしょうか。

    周りにPythonを習熟している者がおらず、上級プログラマーの方たちの一般的な動作がわかりません。。

    なお、最後の③の質問は、元々の質問から逸れますので、もしお時間があれば回答いただければと思います。

    キャンセル

  • 2018/07/20 09:35

    ありがとうございました。
    とても参考に、そして勉強になります!

    これから、書き換えてくださったソースコードをきちんと理解してみます。
    その際、質問等あると思いますので、このページで改めて質問させてください。。そして、もし可能でしたら、ごく簡単で構いませんので、ご回答いただけたら幸いです。。

    ひとまず、この度は本当にありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    thread queueの最大数を設定して、その範囲で回す

    queueの最大数を2個として満杯の場合は待機、 空きができ次第queueを追加するような処理がしたいです。 from threading import Thread, a

  • 解決済

    janomeでcsvを形態素解析したい

    前提・実現したいこと まず、janomeの簡略辞書を作り、 その後、csvのnameの部分を形態素解析したいと考えています。 csvと簡略辞書の中身は以下のようになっています

  • 解決済

    Python メソッド間の変数の呼び出しについて

    Pythonを勉強しておりまして、現在は主にオブジェクト指向の考え方を学んでおります(オブジェクト指向はほとんど初学です)。これまでに書いたシンプルなプログラムをクラスとメソッドで

  • 受付中

    MeCabの文字化け

    実現したいこと pythonで形態素解析を行うためにMeCabをインストールしたのですが、MeCabを起動し日本語を入力してみても、文字化けしてしまい、上手く形態素解析ができていま

  • 解決済

    janomeを使って形態素解析をしたい

    janomeを使って形態素解析をしたいです。 マルコフ連鎖を用いて文章を生成するプログラムの途中で出てしまいました。 self.tagger = Tokenizer.Tagge

  • 解決済

    存在する組み合わせを数えたい

    例えば下のような文字列がある場合 あいう あうえ い うい この4つの文字列のうち同じ文字の組み合わせをもつ文字列を数えたいです。 上の場合、たとえば「あ」と「う」があるのは「あい

  • 解決済

    JanomeのAnalyzer中の引数(token_filters = token_filters)...

    サイト通りのコードを入力したのですが、エラーが出てしまいます。 問題箇所のエラーを調べたのですが、どこを探しても Analyzer(token_filters = token_

  • 解決済

    pythonで感情の値をつける際のエラー

     前提・実現したいこと pythonでjanomeを使っていたらエラーが出た  発生している問題・エラーメッセージ tokenize_result = b.tokenizer

同じタグがついた質問を見る

  • Python 3.x

    6431questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • pandas

    586questions

    Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

  • UTF-8

    109questions

    UTF-8は8ビット符号単位の文字符号化形式及び文字符号化スキームです。データ交換方式、ファイル形式としては、一般的にUTF-8が使われる傾向があります。