Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ruby の統計ツールと Ruby on Rails で分析をしてみた

Avatar for sai-lens sai-lens
November 16, 2025

Ruby の統計ツールと Ruby on Rails で分析をしてみた

Avatar for sai-lens

sai-lens

November 16, 2025
Tweet

More Decks by sai-lens

Other Decks in Technology

Transcript

  1. ⾃⼰紹介 1 • さい/sai-lens • 現在は病院で臨床検査技師として勤務 • プログラミング学習4ヶ⽉⽬ • 現在学習中の技術

    ◦ フロントエンド:JavaScript, React ◦ バックエンド:Ruby, Ruby on Rails @GTposiwill @sye-lens
  2. 今回のデータ分析のきっかけ • 実務で検証したかった検査データ(.xlsx)を統計的に分析したかった • 現在Ruby / Ruby on Railsを勉強中 •

    エクセルで十分だけど、せっかくならRubyで表計算やグラフ作成、統計解析を やってみよう! 3
  3. データ分析する内容 4 • 患者の「たん」の微生物検査を行った検査結果(約12,000件) ◦ 「たん」の見た目(外観)での質を評価する項目 ◦ 「たん」を顕微鏡(×100倍)で見て質を評価する項目 ◦ 顕微鏡で見えた微生物の菌量

    ◦ 炎症を起こしている菌の名前 • 同じ患者の「たん」であれば見た目の外観と顕微鏡で見たときの様子 は相関するはずだが、日常では全く相関しない「たん」に遭遇することも ある • 2項目でどれくらい相関するかを確認し、外れているデータがあればそ の原因を検証する
  4. データ分析する内容 5 • 「たん」の見た目(外観)は6段階評価 • 「たん」を顕微鏡(×100倍)で見た結果も6段階評価 • 最初の解析として、見た目の6段階評価ごとに顕微鏡での評価の出現 割合を表にまとめて、円グラフで可視化する 患者名

    材料 見た目の評価(M & J) 顕微鏡の評価(Geckler) 分離された菌の名前 やまだたろう 吸引たん M1:唾液が多い(サラサラ) G1:口内の細胞が多い 常在菌だけ こばやしはなこ 喀たん P3:膿性部分が多い(ドロドロ) G5:白血球が多い 緑膿菌 さとうじこう 喀たん P2:膿性部分が多い(ドロドロ) G4:白血球が多い 大腸菌 ごとうさぶろう 吸引たん M2:唾液が多い(サラサラ) G2:口内の細胞が多い 常在菌だけ すずきいちろう 喀たん M1:唾液が多い(サラサラ) G3:口内の細胞が多い 常在菌だけ たなかゆうこ 喀たん M1:唾液が多い(サラサラ) G1:口内の細胞が多い 常在菌だけ よしだとみこ 喀たん P1:膿性部分が多い(ドロドロ) G5:白血球が多い 黄色ブドウ球菌 さいとうきみえ 吸引たん M1:唾液が多い(サラサラ) G6:細胞が少ない 緑膿菌 . . . . . . . . . .
  5. データ分析に使⽤した技術スタック (Ruby) データの読み込みから可視化までの流れ Roo gem (Excel読込) Daru gem (データフレーム化) Rubyで

    データ加⼯‧計算 (表記揺れやデー タ⽋損に対処) Rails view + Chartkick gem (結果の可視化) 6
  6. 対象データと前処理 対象データ (1万件以上) 当院で数年間に提出された「たん」 M&J分類 (M1, P1等) Geckler分類 (G1, G6等)

    検出菌 診療科‧病棟 主な前処理 (Ruby) 表記ゆれの統⼀(例: "P1:膿性…" → "P1") M1〜P3 のカテゴリ正規化 Geckler分類の数値抽出(1~6) ⽋損値のハンドリング 7
  7. app/controllers/mj_analyze_controller.rb 8 def load_dataframe path = Rails.root.join("app", "data", "2025-11-12 2年間(修正).xlsx")

    xlsx = Roo::Spreadsheet.open(path.to_s) sheet = xlsx.sheet(0) headers = sheet.row(1).map(&:to_s) data_rows = (2..sheet.last_row).map { |i| sheet.row(i) } df = Daru::DataFrame.rows(data_rows, order: headers) normalize_mj_and_ge(df) end def compute_stats(df) . total = df.nrows mj_summary = mj_levels.map do |lab| count = df.where(df["mj_grade"].eq(lab)).nrows next if count.zero? pct = total.positive? ? (count.to_f / total * 100).round(1) : 0.0 { label: lab, count: count, pct: pct } end.compact . roo gemでエクセルデータ読み込み Daru gemでRubyで扱える形 (Data Frame)に変換 df.whereでデータフレームからデー タを取得して計算
  8. app/view/mj_analysis/_mj_block.html.erb 9 <h3>MJ別 構成比(全体)</h3> <%= pie_chart mj_pie_data, donut: true, legend:

    "bottom" %> <h3>各MJグレード内での Geckler 構成比</h3> <% ["M1", "M2", "P1", "P2", "P3"].each do |lab| %> <% data = mj_ge_pie_data[lab] %> <% next if data.blank? %> <h4><%= lab %></h4> <%= pie_chart data, legend: "right" %> <% end %> pie_chart <ハッシュや配列など> →円グラフを作成 ターミナルでchartkick,chart.jsをインストール $ yarn add chartkick chart.js //javascript/application.js import "chartkick"; import "Chart.bundle"; application.js に import
  9. Ruby/Railsで統計解析してみてわかったこと Excel,Pythonのほうが楽、それでもRuby/Railsを分析ツールとして使ってわかったこと 11 • 解析方法やUIの再利用性が高い ◦ コードという形で解析方法を残すことができる ◦ エクセルデータの内容や量が変わってもデータの前処理を変えるだけ でUIや解析ロジックはそのまま使うことができる

    • データをjavascriptに渡したりせずにグラフの表示をviewで行えるので、 RailsのMVCを活かすことができる • 解析ロジックの記載は慣れていないと難しいと感じたが、初心者でも自分で 統計解析の「仕組み」を作ることができた
  10. まとめ 12 • 臨床現場で遭遇した疑問をRubyを使って分析した • Ruby/Ruby on Railsは「データの前処理」から「UIでの表⽰」まで⼀気通 貫できるというメリットがある •

    エンジニアでなくてもプログラミング⾔語を使ってデータ分析ができた • 追加の検証にも解析ロジックやUIを再利⽤できるので、データ分析に 再現性ができた