プログラムでおかえしできるかな

定年を過ぎて何かの役に立てないかなと始めた元SEのブログです

単語の使用頻度をワードクラウドで表示するアプリの作り方【Python】

このエントリーをはてなブックマークに追加

ワードクラウドを作成しました。
WordCloud ライブラリを使用しています。
日本語の単語分解と品詞付与には mecab-python3 ライブラリを使用しました。
それらの使い方をソースコードと併せて紹介します。

▽アプリの画面

アプリはお使いいただけます 📖 単語の使用頻度をワードクラウドで表示するアプリ【フリー】 🔗
アプリの画面や機能などはこちらの記事で確認できます。
2024/04/06:出力単語数を指定できる機能を追加

本アプリのコードについて説明します。
使用しているプログラミング言語Python です。

目次

このような出力結果を得るために必要な技術がテキストマイニングとワードクラウドです。
このようなというのは、単語を使用頻度が高いものをその頻度に合わせて強調して出力することです。この出力方法をワードクラウドといいます。
そして、与えられたテキストから単語の使用頻度を求める技術をテキストマイニングといいます。
英語の場合、元々テキストが単語単位で区切られているのでテキストマイニングを用いなくてもある程度ワードクラウドを作成することができます。
しかし、日本語の場合、まずテキストを単語に分けなければならないので、テキストマイニングが必須になります。
Python であれば、どちらの技術もライブラリで提供されています。
ライブラリの使い方と今回作成したアプリの作り方を紹介します。

◆ワードクラウド用ライブラリ

ワードクラウドは、テキストデータの中で頻繁に出現する単語を視覚的に表現する方法です。
Python では、ワードクラウドを作成するライブラリが提供されています。
ここでは wordcloud ライブラリを使用します。

◇wordcloudライブラリ

◇クラス:WordCloud

▽コンストラク

  • 【構文】WordCloud()
  • 主な引数(デフォルト値)
    • font_path:OTF, TTFファイルのパス
    • max_words:単語数(200)
    • width  :キャンバスの幅(400)
    • height :キャンバスの高さ(200)
    • min_font_size :最小のフォントサイズ(4)
    • font_step   :フォントのステップサイズを整数で(1)
    • background_color:背景色("black")
    • max_font_size  :最大フォントサイズ(None)。Noneの場合、画像の高さ
    • mode  :画像のモード("RGB")
      透明にしたい場合、"RGBA"にしてbackground_colorをNoneにします
    • colormap:matplotlib のカラーマップ("viridis")
    • include_numbers:数字を含める(False)
    • min_word_length:これより短い文字を除く(0)
    • regexp     :入力テキストをトークンに分割するための正規表現(None)
      re.findall() で動作。None を指定した場合は、「r"\w[\w']+"
      ※「r"[^a-zA-Z0-9\W]+"」で日本語だけを抽出できます
    • stopwords: 出力しない単語のセット
    • collocations:2 つの単語の連語 (バイグラム) を含めるかどうか(True)
      バイグラムとは2つの並んだ単語の出現確率が高いものを指します。
      それを連結するかどうかを指定します
      Trueだと同じ単語が複数回出てくることもありますが氏名などがつながる効果もあります
      バイグラム:【技術解説】bi-gramマルコフモデル を参照

◎メソッド

ワードクラウドを作成するには、基本的に generate() メソッドを使用すれば十分です。

  • generate(text), genarate_from_text(text)
    内部的にprocess_text()を実行してgenerate_from_frequencies()を実行します
    コンストラクタで指定した属性で動作します

    • 戻り値:self
    • 引数
      • text:単語が空白で区切られたテキスト
  • process_text(text):テキストから単語の頻度順を求めます

    • 戻り値:辞書(単語, 頻度)
      属性によって動作が変わります
    • 引数
      • text:単語が空白で区切られたテキスト
    • 影響する主な属性
      • include_numbers:数字を含める(デフォルトFalse)
      • min_word_length:これより短い文字を除く
  • generate_from_frequencies(frequencies[, …])
    単語の使用頻度を辞書で与えてワードクラウドを作図します

    • 引数
      • frequencies :頻度(辞書(str, float))
      • max_font_size:最大フォントサイズ(属性の代わりに使用)
  • to_file(filename):画像ファイルにエクスポート
    指定した拡張子にあったフォーマットで保存します

コマンドライン

日本語の場合、コマンドラインで使用することはあまりないかもしれません。
ただし、既に単語単位に区切られているテキストであれば、使用可能です。
参考までに、サンプルを紹介します。

例:wordcloud_cli --text mytext.txt --imagefile wordcloud.png

テキストマイニング用ライブラリ

ワードクラウドに渡すテキストは、単語単位に分けておく必要があります。
そのためにテキストマイニングを使用します。
Python では、テキストマイニングを作成するライブラリが提供されています。
ここでは mecab-python3 ライブラリを使用します。
これは 日本語テキストマイニングMeCabPython から操作できるようにしたものです。

mecab-python3ライブラリ

  • インストール   :pip install mecab-python3 (辞書は含まれません)
    MS Visual C++が必要(Windows wheelsのため)
    MS Visual C++がない場合は別記事『C++ビルドツールがない』を参照
  • 辞書のインストール:pip install unidic-lite (一例)
  • インポート    :import MeCab

◇辞書

mecab-python3 を使用するには辞書のインストールも必要です。
使い易い辞書として unidic と unidic-lite があります。
サイズが小さくて個別にダウンロードする必要がない unidic-lite を使用しました。

【辞書】

  • unidic

    • インストール:pip install unidic、容量:1GB
    • インストール後、ダウンロードが必要。パスの指定不要
      ダウンロードコマンド:python -m unidic download
    • MeCab.Tagger() の結果の例:「兼六」の解析結果
      兼六\t名詞,固有名詞,一般,,,,ケンロク,兼六,兼六,ケンロク
      ,兼六,ケンロク,固,"","","","","","",固有名,ケンロク,ケンロク
      ,ケンロク,ケンロク,"0","","",3147910413951488,11452\n
  • unidic-lite:UniDic の縮小版

    • インストール:pip install unidic-lite、容量:250MB
    • インストール後のダウンロード不要。パスの指定不要。
      pyinstallerで作成したexeは80MBくらいだった
    • MeCab.Tagger() の結果の例:「兼六」の解析結果
      兼六\tケンロク\tケンロク\t兼六\t名詞-固有名詞-一般\t\t\t0\n
  • ipadic:長年メンテナンスされていない ⇒ 提供サイトにも使うなと出ています

  • jumandic:長年メンテナンスされていない

使用する辞書によって出力フォーマットが異なります。ご注意ください。
mecab-python3 は unidic と unidic-lite の両方がインストールされていると unidic を使用します。こちらもご注意ください。

◇基本的な使い方

mecab-python3 の基本的な使い方は、Tagger インスタンスを作成し、parse() メソッドを実行することです。
Tagger コンストラクタでは、基になっている MeCab を呼び出すコマンド引数を引数として与えて動きを制御します。

>>> import MeCab
>>> wakati = MeCab.Tagger("-Owakati")
>>> wakati.parse("pythonが大好きです").split()
['python', 'が', '大好き', 'です']

mecab-python3 · PyPI

◇クラス:Tagger

コンストラクタでは引数にMeCabの起動引数を指定します。

▽コンストラク

  • 【構文】MeCab.Tagger(rawargs)
  • 引数
    • rawargsMeCabコマンドラインオプション
      一つの文字列の中に複数のオプションを指定します
      指定値は空白で区切ってもよい。raw文字列は使えません
      主なコマンドラインオプション
      • -r, --rcfile=FILE:リソースファイル名指定
      • -d, --dicdir=DIR:システム辞書のフォルダ指定
        辞書 unidic, unidic_lite がインストールされていると自動判別
      • -u, --userdic=FILE:ユーザー辞書ファイル名指定
      • -O, --output-format-type=TYPE:出力フォーマット
        例:-Owakati-Odump
      • -o, --output=FILE:出力ファイル名
      • -F, --node-format=STR:Nodeの出力方式を指定
      • -U, --unk-format=STR:未知語の出力方式を指定
      • -E, --eos-format=STR:EOSの出力形式を指定

◎メソッド

  • parse(text):解析を実施
    • text:解析対象のテキスト

◇出力内容の調査

当初、MeCab の使用方法について説明しているサイトが見つからなかったので、実際に使用して出力内容を調査しました。
Tagger コンストラクタの引数の与え方で出力内容が異なります。

入力:「ここは、日本です」

▽引数なし

ここ\tココ\tココ\t此処\t代名詞\t\t\t0\n
は\tワ\tハ\tは\t助詞-係助詞\t\t\t\n
、\t\t\t、\t補助記号-読点\t\t\t\n
日本\tニッポン\tニッポン\t日本\t名詞-固有名詞-地名-国\t\t\t3\n
です\tデス\tデス\tです\t助動詞\t助動詞-デス\t終止形-一般\t\n
EOS\n

※当初、品詞を使いたいのでこちらの出力方法を採用しました。
 行単位に分割した後にタブで区切られているのをさらに分割します。
 そのときに要素数の少ない値があるので考慮します。
 後に出力フォーマットを独自に指定する方法に変えました。

▽-Owakati

ここ は 、 日本 です \n

▽-Odump

0 BOS BOS/EOS,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,* 0 0 0 0 0 0 2 1 0.000000 0.000000 0.000000 0\n
11 ここ 代名詞,*,*,*,*,*,ココ,此処,ここ,ココ,ここ,ココ,和,*,*,*,*,ココ,ココ,ココ,ココ,*,*,0,*,* 0 6 1 1 1 6 0 1 0.000000 0.000000 0.000000 4074\n
21 は 助詞,係助詞,*,*,*,*,ハ,は,は,ワ,は,ワ,和,*,*,*,*,ハ,ハ,ハ,ハ,*,*,*,"動詞%F2@0,名詞%F1,形容詞%F2@-1",* 6 9 662 662 1 6 0 1 0.000000 0.000000 0.000000 4551\n
27 、 補助記号,読点,*,*,*,*,,、,、,,、,,記号,*,*,*,*,,,,,*,*,*,*,* 9 12 5974 5974 1 3 0 1 0.000000 0.000000 0.000000 825\n
36 日本 名詞,固有名詞,地名,国,*,*,ニッポン,日本,日本,ニッポン,日本,ニッポン,固,*,*,*,*,ニッポン,ニッポン,ニッポン,ニッポン,*,*,3,*,* 12 18 4793 4793 1 2 0 1 0.000000 0.000000 0.000000 2270\n
64 です 助動詞,*,*,*,助動詞-デス,終止形-一般,デス,です,です,デス,です,デス,和,*,*,*,*,デス,デス,デス,デス,*,*,*,"形容詞%F2@-1,動詞%F2@0,名詞%F2@1",* 18 24 298 298 1 6 0 1 0.000000 0.000000 0.000000 8097\n
73 EOS BOS/EOS,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,* 24 24 0 0 0 0 3 1 0.000000 0.000000 0.000000 4242\n'

◇出力フォーマット

MeCab は出力のフォーマットを再定義することができます。詳細は脚注のリンクを参照 1
その機能を使用して辞書ごとに独自の出力形式を定義しています。
出力フォーマットは、任意の文字列で名前付けができます。
これを出力フォーマットタイプと呼びます。
出力フォーマットタイプを呼び出すコマンドラインオプションが、-O です。

Tagger コンストラクタで -O オプションを指定しない場合は、辞書のデフォルトの出力フォーマットタイプが使用されます。

▽unidic_liteの出力フォーマット

node-format-unidic = %m\t%f[9]\t%f[6]\t%f[7]\t%F-[0,1,2,3]\t%f[4]\t%f[5]\t%f[23]\n
unk-format-unidic  = %m\t%m\t%m\t%m\t%F-[0,1,2,3]\t%f[4]\t%f[5]\t0\n
bos-format-unidic  =
eos-format-unidic  = EOS\n

出力フォーマットタイプは、??\site-packages\unidic_lite\dicdir\dicrc ファイルに設定されています。

▽各記号の意味

  • %m  :表層文字列
  • %f[9]:発音形出現形
  • %f[6]:語彙素読
  • %f[7]:語彙素
  • %F-[0,1,2,3]:品詞の大分類、中分類、小分類、細分類を「-」で接続
  • %f[4]:活用型
  • %f[5]:活用形
  • %f[23]:アクセント型

これらの記号の意味は、「MeCab のサイト 」と dicrc ファイルのコメントから判断します。
dicrc ファイルのコメントの説明は「「UniDic」国語研短単位自動解析用辞書|FAQ サイト 」で確認できます。

mecab-python3で出力フォーマットを指定するには

出力フォーマットの指定(--node-format など)は MeCabコマンドラインオプションでも指定可能なのですが、使用する辞書によって機能しません。
今回使用した unidic_lite も該当します。
詳細は不明ですが、出力フォーマットタイプが定義済みの辞書ではないかと思われます。

そのような辞書を使用しても出力フォーマットを機能させるには、出力フォーマットタイプをクリアします。
具体的には、-O "" オプションを追加します。(根拠 23

その上で出力フォーマットを指定するオプション 45 を指定します。

本アプリでは以下のようにしました。

  • 出力フォーマットタイプを初期化:-O ""
  • Node 出力方式を「表層文字列」、「品詞」に設定:-F "%m\\t%F-[0,1,2,3]\\n"
  • EOS を出力しない設定:-E ""

▽コード:MeCabで出力フォーマットを指定

    MeCab.Tagger('-O "" -F "%m\\t%F-[0,1,2,3]\\n" -E ""')

MeCab を直接利用している場合もオプションの使い方は同じです

◆ワードクラウドの実装

◇ワードクラウドの作成

ワードクラウドの作成は、WordCloud クラスに単語を空白で区切られたテキストを渡して作成します。
WordCloud コンストラクタでは、日本語を表示するために日本語対応のフォントを指定します。フォントの指定にはフォントファイル名を使用します。

▽手順:ワードクラウド作成

  1. テキストから単語に分けて空白でつないだ文字列を作成:create_wakachigaki()
  2. ワードクラウドを作成して表示:view_word_cloud()
    メソッド内は以下の通り
    1. WordCloud インスタンスの作成:WordCloud()
      • 日本語フォントの指定:font_path
      • 背景色の指定(デフォルトは黒):background_color
      • 幅、高さの指定:width, height
      • 連語を連結しない指定:collocations
      • 非表示にする単語の指定:stopwords
    2. ワードクラウドイメージを作成:generate()
    3. WordCloud オブジェクトのデータを Axes オブジェクトにイメージとして表示
    4. canvas を描画
  3. 初期状態で無効だったボタンを有効にする

▽コード:ワードクラウド作成

    def create_wordcloud(self, text:str):
        """
        ワードクラウドの作成
        """        
        if not text: return
        self.words = self.create_wakachigaki(text)  # テキストマイニングして単語のリストを取得
        mw = self.view.var_max_words.get()          # 出力単語数を取得
        self.view_word_cloud(max_words=mw if mw else 50)    # ワードクラウドの作成
        self.view.btn_save.config(state=tk.NORMAL)  # ボタンを有効にする
        self.view.btn_once.config(state=tk.NORMAL)  # ボタンを有効にする
        self.view.btn_stop_w.config(state=tk.NORMAL)  # ボタンを有効にする
    def view_word_cloud(self, stopwords:str="", max_words:int=50):
        """
        ワードクラウド生成    generateであれば単語の出現頻度も調べる
        Args:
            str:    非表示ワード(カンマ区切り)
            int:    出力単語数
        """
        self.wc = WordCloud(font_path="meiryo.ttc"  # 日本語フォントを指定
                    , background_color="white"
                    , max_words=max_words           # 出力する単語数
                    , width=800
                    , height=400
                    , collocations=False            # 連語の連結
                    , stopwords=set(stopwords.split(','))    # {"こと", "ため", "ない"}
                    )
        self.wc.generate(" ".join(self.words)) # 日本語の単語を空白でつなげて渡す

        # ワードクラウドをAxesに追加
        self.view.ax.imshow(self.wc, interpolation="bilinear")  # データをイメージに
        self.view.canvas.draw()                                 # 表示

◇ワードクラウド(matplotlib)をTkinterで表示

WordCloud クラスは内部で matplotlib を使用してワードクラウドを作成しています。
したがって、WordCloud の出力イメージを Tkinter で表示することは、matplotlib の出力イメージを Tkinter で出力することになります。

そのために matplotlib の FigureCanvasTkAgg クラスを使用します。

使用するにはインポートが必要です。

   from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

matplotlib ライブラリでグラフを出力するには、Figure オブジェクトを作成してそこに Axes オブジェクトを追加します。
Figure オブジェクトが台紙で、Axes オブジェクトが枠というイメージです。
この Axes オブジェクトの枠に WordCloud オブジェクトのデータで作図します。

また、Figure オブジェクトの中の Axes オブジェクトが隙間なく配置されるように、レイアウトエンジンを指定します。

▽手順

  • matplotlib の Figure インスタンスを作成:Figure()
    レイアウトエンジンを設定して隙間を無くす:set_layout_engine()
  • Axesインスタンスを作成して Figure オブジェクトに追加:add_subplot()
    軸を非表示に設定:set_axis_off()
  • FigureCanvasTkAgg インスタンスを作成:FigureCanvasTkAgg()
    引数:Figureオブジェクト、親ウィジェット
  • FigureCanvasTkAgg オブジェクトの TkinterCanvas 部分を取得:get_tk_widget()
  • 配置:pack(), grid() など

  • WordCloud オブジェクトのデータで作図:imshow()
  • canvas を更新:draw()

▽コード:

    def create_canvas(self, parent):
        """
        matplotlibで作成した図をTkinterで表示
        """
        # matplotlibのFigure作成
        fig = Figure(figsize=(8, 6))
        fig.set_layout_engine('constrained')    # 隙間をなくすためレイアウトエンジンを指定
        # ワードクラウド用Axesを作成
        self.ax = fig.add_subplot(111)  # Axesを作成
        self.ax.set_axis_off()          # 軸を非表示
        # ワードクラウド用キャンバス作成
        self.canvas = FigureCanvasTkAgg(fig, parent)
        self.canvas.get_tk_widget().pack()
        # ワードクラウドをAxesに追加
        self.view.ax.imshow(self.wc, interpolation="bilinear")  # データをイメージに
        self.view.canvas.draw()                                 # 表示

◇画像の保存

WordCloud オブジェクトを作成し、Genarete() メソッドでワードクラウドを作成した後にそれを画像として保存することができます。

▽手順:画像の保存

  1. ファイル選択ダイアログを表示してパスを取得:asksaveasfilename
  2. WordCloud オブジェクトから画像を保存:to_file()

▽コード:画像の保存

    def save_image(self, event=None):
        """
        ワードクラウドを画像ファイルに保存
        """
        path = filedialog.asksaveasfilename(filetypes=[("イメージ", "*.png")])
        if path and hasattr(self, 'wc'):
            self.wc.to_file(path)

◇FigureCanvasTkAggクラス

matplotlib ライブラリの Figure クラスと TkinterCanvas クラスを橋渡しするクラスです。
本アプリで使用しているメソッドを簡単に説明します。

◎メソッド

◇Axesクラス

本アプリで使用しているメソッドを簡単に説明します。

◎メソッド

  • imshow(X, cmap, norm, *, aspect, interpolation, alpha, vmin, vmax, origin, extent, interpolation_stage, filternorm, filterrad, resample, url, data, **kwargs)
    データをイメージとして表示
    • 主な引数
      • X:画像データ(配列状または PIL イメージ)
      • interpolation:補間 指定した保管方法でアップまたはダウンサイジングされます
        'none'、'bilinear' など

テキストマイニングの実装

テキストマイニング

▽手順:テキストマイニング

  1. Tagger インスタンスを作成:MeCab.Tagger()
    MeCabコマンドラインオプションを指定
    表層文字\t品詞\n... を作成
  2. テキストを解析:parse()
  3. [[表層文字列, 品詞]...]を作成:splitlines()split()
  4. 品詞が名詞、形容詞、接頭辞、接尾辞のものだけを抽出し、英数字を省いた単語のリストを作成

▽コード:テキストマイニング

    def create_wakachigaki(self, text:str):
        """
        テキストマイニング
        日本語を単語分割し品詞を付与し単語と品詞のタプルのリストをall_tokensにセットする
        そのうち半角英数字記号を除き、品詞が名詞|形容詞|接頭辞|接尾辞のものをリストで返す
        Returns:
            list:   単語のリスト
        """
        # MeCabの出力を表層文字列、品詞にし、EOSを出力しないで使用する。
        tagger = MeCab.Tagger('-O "" -F "%m\\t%F-[0,1,2,3]\\n" -E ""')  # raw文字列は使えない
        tokens = tagger.parse(text)
        # [[表層文字列, 品詞]...]を作成
        self.all_tokens = [l.split("\t") for l in tokens.splitlines()]
        # 品詞が名詞|形容詞|接頭辞|接尾辞のものだけを抽出。英数字を省く
        tokens = [s[0] for s in self.all_tokens if re.match('名詞|形容詞|接頭辞|接尾辞', s[1]) and re.match(r"[^a-zA-Z0-9\W]+", s[0])]
        return tokens

◇テキストファイル読み込み

テキストファイルの読み込みは複数ファイルを対象にします。
テキストファイル以外を指定された場合、例外が発生するのではじきます。
エンコードは、UTF-8 と Shift-JIS を対象にします。

▽手順:テキストファイル読み込み

  1. 複数ファイル選択ダイアログを表示
  2. パスが返ってきたか確認
  3. それぞれのパスごとにテキストを取得
    1. UTF-8エンコードして読めたらそれを取得
    2. 読めなかったら Shift-JIS でエンコードして読めたら取得
    3. 読めなかったら何もしない

▽コード:テキストファイル読み込み

    def load_text_file(self):
        """
        テキストファイルの読み込み(ファイル選択ダイアログ表示)
        読み込んだテキストはself.textへ設定
        """
        self.text = ""
        paths = filedialog.askopenfilenames(
                filetypes=[("テキスト", ".txt"), ("md", ".md"), ("すべて", "*")])
        if paths:
            for path in paths:
                try:
                    with open(path, encoding='utf-8') as f:
                        self.text += f.read()
                except UnicodeDecodeError as e:
                    try:
                        with open(path, encoding='shift_jis') as f:
                            self.text += f.read()
                    except UnicodeDecodeError as e:
                        pass         # エンコードエラーをはじく テキストファイル以外も

◇貼り付け

コンテキストメニューを表示して、コピーされたテキストを貼り付けて、ワードクラウドを作成します。

コンテキストメニューの作り方についてはこちらの記事を参照してください。
 📖 コンテキストメニュー - gTTSとmpg123で作るテキスト読み上げアプリ【Python】 🔗

▽手順:貼り付け

  1. クリップボードのデータを取得:clipboard_get()
  2. ワードクラウドを作成:create_wordcloud()

▽コード:貼り付け

    def do_paste(self, event=None):
        """
        ペースト処理
        """
        text = self.clipboard_get()     # クリップボードから文字列取得
        self.my_ctr.create_wordcloud(text)
        # ペーストの設定
        self.bind('<Control-v>', my_frame.do_paste)
        self.bind('<Button-3>', my_frame.show_cmenu)    # 右クリックでコンテキストメニュー表示

◆非表示単語指定

シンプルダイアログを使用して非表示にする単語を入力してもらいます。
入力された単語を非表示単語としてワードクラウドを再作成します。

▽手順:単語入力

  1. 文字列の問合せダイアログを開き、に有力された単語を取得:askstring()
  2. 取得した文字を保存(次回も同じ文字を表示するため)
  3. ワードクラウドを再表示:view_word_cloud()

▽コード:単語入力

    def input_stopword(self, event=None):
        """
        非表示にする単語をの入力がダイアログを表示し入力された単語を設定
        """
        s = simpledialog.askstring('非表示単語指定', '表示したくない単語をカンマ区切りで入力してください', initialvalue=self.stopword)
        if s == None: return    # キャンセルの場合は何もせず戻る
        self.stopword = s
        mw = self.var_max_words.get()
        self.my_ctr.view_word_cloud(s, max_words=mw if mw else 50)

Tkinterのシンプルダイアログ

データを入力するダイアログを表示し、入力したデータを返します。
使用するにはインポートが必要です。

   from tkinter import simpledialog

以下の各型の値を入力をするダイアログが用意されています。

  • askfloat(title, prompt, **kw)
  • askinteger(title, prompt, **kw)
  • askstring(title, prompt, **kw)

◆1回使用単語表示

▽手順:1回使用単語表示

  1. テキストマイニング結果から半角英数字と1文字のものを除く:内包表記
  2. 同じ単語の数をカウント:collections.Counter()
  3. カウント数が1だけのものを抽出:内包表記
  4. ソート:sort()
  5. メッセージボックスに表示:messagebox.showinfo()

▽コード:1回使用単語表示

    def show_once_words(self, event=None):
        """
        一回使用単語をダイアログ表示
        """
        # 英数字を省く。一文字を除く
        tokens = [s[0] for s in self.all_tokens if re.match(r"[^a-zA-Z0-9\W]+", s[0]) and len(s[0]) > 1]
        c = collections.Counter(tokens)
        words = [w for w, count in c.items() if count == 1]
        words.sort()
        messagebox.showinfo("1回使用単語", "\t".join(words))

◇メッセージボックス

Tkinter には簡単なテキストをダイアログ表示するメッセージボックスが用意されています。
仕様にはインポートが必要です。

インポート:from tkinter import messagebox

メッセージボックスには以下のようなものが用意されています。
本アプリでは、showinfo() メソッドを使用しました。

メソッド ボタン
showinfo(title=None, message=None, **options) OK
showwarning(title=None, message=None, **options) OK
showerror(title=None, message=None, **options) OK
askquestion(title=None, message=None, **options) YES NO
askokcancel(title=None, message=None, **options) OK CANCEL
askretrycancel(title=None, message=None, **options) RETRY CANCEL
askyesno(title=None, message=None, **options) YES NO
askyesnocancel(title=None, message=None, **options) YES NO CANCEL

Tkinterによる画面構築

Tkinterティーキンター)は Python が標準で提供している GUI パッケージです。
他のプログラムの開発ツールで提供されているようなルック&フィールな GUI ツールではありません。
従って、画面を構成するには、すべてコードを書く必要があります。

Tkinter を使用するにはインポートが必要です。

  • インポート:import tkinter as tk

慣例的に tk と別名を付けるようです。

Tkinterの使用ウィジェット

Tkinter がサポートする GUI の部品をウィジェット (widget) と呼びます。

ここでは次のウィジェットを使用しています。

◇使用ウィジェット

ウィジェットは基本的にインスタンスを作成し、表示テキストや表示方法などを指定して使用します。

今回使用しているウィジェットです。

パッケージ ウィジェット 用途 見た目
tkinter Frame
フレーム
ウィジェットの受け皿
tkinter Button
ボタン
押すと処理が動くボタン
tkinter Label
ラベル
文字、画像の表示
tkinter Entry
エントリー
テキストを入力するボックス t03

◇画面構成 - フレーム構造

プログラムを作るにあたって、どのような画面にするか決めなくてはなりません。画面構成を考えるということですね。
画面を構成するというのは、GUI 部品(ウィジェット)を画面に配置することです。
ウィジェットは設定したテキストに合わせてサイズが決まるので、そのまま使用しても画面構成上問題ないものと、広げないと見栄えが良くないものが出てきます。
今回は Entry の幅だけ指定しました。

今回の画面構成です。

  • frm_canvas(Frame):単純なタイマーの時間選択し
  • btn_open(Button):ファイル選択ボタン
  • btn_save(Button):画像保存ボタン
  • btn_once(Button):1回使用単語ボタン
  • btn_stop_w(Button):非表示単語指定ボタン
  • lbl_max_words(Label):「出力単語数」を表示
  • ety_max_words(Entry):出力単語数を編集

※「frm_canvas」などはプログラムで使用した変数名です。()内はクラス名です。

ウィジェットの配置 - pack

▶説明は別記事を参照してください
 📖 ウィジェットの配置 - pack - SQLクライアントアプリの作り方(Tkinterで表)【Python】 🔗

◇動作をウィジェットに割り当てる - バインド

▶説明は別記事を参照してください
 📖 動作をウィジェットに割り当てる - Excel viewerアプリの作り方(Tkinterでタブと表)【Python】 🔗

◇ファイル選択ダイアログ

▶説明は別記事を参照してください
 📖 ファイル選択ダイアログ - CSV viewerアプリの作り方(ドラッグアンドドロップ)【Python】 🔗

※書き込みファイルの選択ダイアログも使い方は読み込みと同じです。

◆バイナリの作成

pyinstaller でバイナリを作成する場合、バイナリに辞書を含ませるためにオプションを設定する必要があります。
使用するオブジョンは、--collect-data オプションです。
これは、指定したモジュールからデータを収集してバイナリに含めるオプションです。

本アプリでの指定は次の通りです。

pyinstaller -F --collect-data unidic_lite word_cloud.py

※本来は -w オプションを付けたかったのですが、付けるとウイルス検知ソフトに誤認識されるので付けませんでした。

◆ソースの取得

全体のソースはこちらから取得できます。

◆さいごに

ワードクラウドを作成するアプリの作り方を紹介しました。
作ろうと思ったきっかけはこちらの記事です。

テキストをアップロードして使うのが好みじゃないので、作ってみることにしました。
はじめ、Google Gemini にお願いしたら簡単に動くものが示されるかと思ったら、
意外に動かなくて、結局、自分で検索して作ることにしました。
生成 AI の使い方が下手なのか、どうも世の中の人が言うほど動くものになりません。

アプリをコマンドプロンプトの出ない exe にしたかったのですが、そうするとavast がウイルスと誤認識してしまうので、コマンドプロンプトの出る形で提供しました。ご容赦ください。

プログラムを作っている時にはわからなかった MeCab の出力フォーマットの指定方法が、この記事を書いている時に分かりました。
解説記事を書くために調べることで新たな理解が産まれました。

同じように解説記事を書いている時に出力単語数を抑えていたことを思い出しました。
出力結果が大差ないのならそのままにしようかと思ったのですが、結構見た目が異なるので、機能追加することにしました。

アプリは、まずは出す、気になるところは直す、がいいですよね。

ご要望があればお気軽に。


あわせて読みたい 📖 音声入力で文章作成するアプリの作り方【Python】 🔗

◇ご注意

本記事は次のバージョンの下で動作した内容を基に記述しています。

  • Python 3.8.5
  • mecab-python3 1.0.8
  • unidic-lite 1.0.8
  • wordcloud 1.9.3

◇免責事項

ご利用に際しては、『免責事項』をご確認ください。
お気づきの点がございましたら『お問い合わせ』からお問い合わせください。

◆参考

投稿: