落ちこぼれナースの統計チャレンジ

元落ちこぼれ看護師(保健師)が、私と同じく統計にドキドキしている看護学生や保健師さんに、簡単な言葉で届けるために始めたブログです。

看護職がストレスチェック23項目のWebアプリを作ってみた


↓早速Webアプリのリンクを貼っておくので、よろしければ使ってみてください。
感想や改善点などお気づきの点がありましたら、本ブログのコメントかXで教えていただけると大変助かります!!よろしくお願いいたします!!

https://stress-check-23-zfdvky7at5epgn2jxsxbda.streamlit.app/#23

本格的なWebアプリ開発経験がなかった私が厚生労働省ホームページを参考にストレスチェック簡易版(23項目)のアプリを作りました。

もし好評であれば57項目版の日本語版・英語版、80項目版を作ることも考えています。

※免責事項
本ツールは、厚生労働省が公開している「職業性ストレス簡易調査票(23項目)」を参考に作成したもので、
ご自身のストレス傾向を簡単に振り返ることを目的としています。
医師・保健師・心理士等による診断や専門的な評価を代替するものではありません。
結果に不安を感じた場合や体調に変化がある場合は、医療機関または職場の産業保健スタッフにご相談ください。

入力された内容は保存・送信されず、完全に匿名で利用できます。
本ツールの利用によって生じたいかなる結果についても、作者は責任を負いかねます。

アプリの構成

  1. ストレスチェックの選択肢をボタン式で選ぶ
  2. 「PDFレポートを作成」をクリック
  3. 「PDFをダウンロード」でダウンロードする
  4. PDFでストレスチェックの結果とA項目・B項目それぞれの結果の棒グラフが出る

以上です。なるべくお手軽さを追求しました。

それに、先ほど免責事項で述べた通り、完全に匿名で使えます。ブラウザを離れた後は入力した情報が破棄される仕様になっています。

結果に出てくるレポートIDは、自動的に無作為な英数字で発行されます。
このIDは内容や個人情報とは一切関係がなく、生成されるたびに異なる番号になります。
結果を区別するための目印としてご利用ください。

尚、57項目版や80項目版を作る機会があれば、レーダーチャートが表示される仕様を作ろうと考えています。

2025年11月11日追記:

本アプリのご意見やアドバイスを頂きありがとうございました。

頂いたアドバイスを踏まえ、取り急ぎ下記のように機能を修正いたしました。

  • 選択肢が何も選ばれていない状態をデフォルトとする
  • 回答していない質問がある場合、エラーが出るようにする
  • PDFの出し方についての説明文を加える

※これより下は技術的な話になります。興味がない方はここまでで画面を閉じてもOKです!使った感想をお待ちしています!!


技術的なお話。

Webアプリを作るのに使ったツールは、

  • GitHub
  • Streamlit Cloud

これらは、ななな何と無料で使えます。こんなハイスペな機能がひぇーすぎて比叡山延暦寺です。

特にStreamlit CloudはPythonだけでWebアプリが作れてしまうので大助かりでした。神様仏様Streamlit Cloud様です。

ただし、デザインが限られているのが難点です…まぁ使えたらいいのだよこういうのは。

Streamlit Cloud文字化け戦記

特に苦労したのは、日本語の文字化けとの戦いでした。

せっかく保存したPDFが数字以外全部文字化けしたこともありました。

考えられる原因は大きく分けて2つです。

  1. Streamlit Cloud に日本語フォントがプリインストールされていない
    IPAexGothicが存在しないため、フォント指定が無効になる
  2. japanize-matplotlibが依存しているdistutilsがPython3.12以降で非推奨
    import japanize_matplotlibの時点でエラーになることもある。

そのため、フォントファイルを自前で配置し、matplotlibやPDFで直接指定するのが最も確実です。

私がとった解決策はこちら。

1. IPAexフォントをダウンロードしてリポジトリに配置

IPA公式サイトからIPAexGothicを取得します。

ダウンロードしたZIPを展開し、
ipaexg.ttfを GitHubリポジトリの直下 に配置します。

2. matplotlibで明示的にフォント設定

import matplotlib.pyplot as plt
import matplotlib.font_manager as fm

# 中略

# フォントを指定
font_prop = FontProperties(fname="ipaexg.ttf") # リポジトリに同梱したフォント

# 棒グラフ描出
plt.figure(figsize=(5,4))
plt.bar(["A(1〜11)", "B(12〜23)"], [A_total, B_total],
        color=["#66b3ff", "#99cc99"], edgecolor="black")

plt.title(f"ストレスチェック結果(レベル {level})", fontproperties=font_prop, fontsize=13)
plt.ylabel("合計スコア", fontproperties=font_prop, fontsize=11)
plt.xticks(fontproperties=font_prop) # 指定したフォントを使用
plt.yticks(fontproperties=font_prop) # 指定したフォントを使用
plt.ylim(0, 50)
plt.tight_layout()
plt.savefig("stress_chart.png", dpi=150)
plt.close()

3. PDFも文字化けを防ぐ

from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.cidfonts import UnicodeCIDFont

# PDF用のフォントを登録する
pdfmetrics.registerFont(UnicodeCIDFont('HeiseiMin-W3'))
pdfmetrics.registerFont(UnicodeCIDFont('HeiseiKakuGo-W5'))

# 中略

# PDFを作成する関数を作る
def generate_pdf(A_total, B_total, level, comment):
    styles = getSampleStyleSheet()
    style_title = ParagraphStyle("Title", parent=styles["Heading1"], fontName='HeiseiKakuGo-W5',
                                 alignment=1, fontSize=18, textColor=colors.darkblue) # フォントを指定
    style_normal = ParagraphStyle("Normal", parent=styles["Normal"], fontName='HeiseiMin-W3',
                                  fontSize=11, leading=14) # フォントを指定
    style_sub = ParagraphStyle("Sub", parent=styles["Normal"], fontName='HeiseiKakuGo-W5',
                               fontSize=12, textColor=colors.grey) # フォントを指定

# 以下略

やはりフォントを指定するのが一番安定するやり方でした。ここはめんどくさいけどしょうがない。

「他にもっといいやり方知ってるよー」という方、ぜひ教えていただけると大変助かります…何卒よろしくお願いいたします。


コメントを残す