DPCデータの分析とかやるブログ

DPCデータの分析なんかをテキトーにやってます。

Electronアプリ DPCチェッカー0.2を公開

えー、前回のリリースから一ヶ月以上サボってましたが、0.2が出来ましたので公開します。
例によってこちらからどうぞ。

変更点

Python版にあったダッシュボード機能を移植しました。
今回こんなに時間がかかったのは、方向性を決めあぐねて、色々フレームワークをいじって遊んでたからです。
JavaScriptの世界は本当にジャングルみたいに繁栄してますね・・・
一時期は「フロント部分をReactで書き直す」とか正気じゃないことを考えてました。
その後は「Reactはやり過ぎだ。Vue.jsで書き直せばいいだろう」と思ってました。うーん、迷走ですね!
(そもそも力を入れるべきはそこではない)

今後の方向

いい加減単月データだけを見る構造は卒業して、最低でも1年分は保存出来るようにしたいですが、設計どうするか迷っています。
割と見切り発車でアップデートするかも知れません。
あとPythonベースの高度なダッシュボードも作ってみたいなあ・・・

Pandasでささっと前年度比較

毎月レセプトが終わると、前年同月比較をやることが多いです。
まあ、手術がガクンと落ちたり上がったり、どうしても波があるからです。
今回は、EFからささっとデータを取ってくる方法を考えてみました。 わかりやすく、今年のデータはdf17、去年のデータはdf16としましょう。

df17 = pd.read_sql("""select 診療科区分,解釈番号,診療明細名称,出来高実績点数,行為回数
from etable17
Where データ区分 BETWEEN 50 AND 59
AND 解釈番号 LIKE 'K%'
AND 解釈番号 NOT LIKE 'K92%'""",connection)

df16 = pd.read_sql("""select 診療科区分,解釈番号,診療明細名称,出来高実績点数,行為回数
from etable16
Where データ区分 BETWEEN 50 AND 59
AND 解釈番号 LIKE 'K%'
AND 解釈番号 NOT LIKE 'K92%'""",connection)

ひとまず手術手技だけに着目することにします。
解釈番号がKで始まるものに固定し、かつK92系(輸血です)を除いて、純粋に手術手技だけを見てみましょう。

df16['year'] = 16
df17['year'] = 17

df_merged = pd.concat([df16,df17])

あとで集計しやすいように、yearカラムを追加して年を入れます。
pd.concatはデータフレームを縦方向に連結する関数です。SQLでいうところのUNIONですね。

df_merged.groupby(['診療科区分','year']).describe()

で診療科区分別の状態を、年別にサクッと確認できます。
また、

df_merged.sort_values(by='出来高実績点数', ascending=False)

とすれば、手技の高い順にソートをすることも出来ます。

また、メソッドは連結が可能です。
つまり、

df16.groupby(['診療科区分','診療明細名称']).sum().sort_values(by='出来高実績点数', ascending=False)

こうすれば、診療科区分・手技別に総計を出し、金額順に並び替える、という処理がワンライナーで出来ます。
こんな風に、その場その場の問題をぱぱっと解決するのにPandasは便利ですね。

EFファイル統合スクリプトをアップしました

4月分のレセプトチェックのため、EF統合ツールを使ったところ「2017年度以降のデータが入っています」と蹴られました。 あれ?と思って調べてみたら…PRISMのEF統合ツール、今年度分は6月公開予定なんですね!(白目

うーん、困りました。そういえば、去年も同じようなことがあって困ってた記憶があります。
ほじくり返すと、どうやらEF統合を自力でやろうとしてたみたいですね。
仕方ないので今年もそうしますが、去年のに少しだけ手を加えて、ヘッダを用意しなくても使えるように修正しました。
こちらEF統合(2016).pyをご利用ください。
EファイルとFファイルのあるフォルダに置いて実行すれば、outputEF.txtが出力されます。

なお、このスクリプトの用途はあくまでDB取り込み用であり、提出仕様ではないのでご注意を。
エンコーディングUTF-8になってるので、このまま提出すれば100%弾かれます。

Bokehで動的なグラフを描画する

そもそもBokehって?

大分前に一度紹介しましたが、PythonのグラフライブラリにBokehというものがあります。
Pythonのデータ可視化というと、matplotlibが圧倒的なデファクトになってます。
そのラッパーであるseabornも有名で、最近のPython本を見るとseabornを使う例も多いですね。
今回紹介するBokehはかなり違った出自で、HTMLを吐き出すのが特徴です。ライブラリはPython側とJavaScript側に分かれており、実際の描画はJavaScript側が行います。
また、グラフの描画レベルが2つに分かれているのも特徴です。

ローレベルのbokeh.plotting

  • 折れ線グラフ、単純な散布図、棒や円などを描画できる
  • D3.jsほどローレベルではないが、割りと近い感じ
  • 当然自由度は高いが、これでグラフを組み上げるのは大変そう…

ハイレベルのbokeh.charts

  • 既に用意された形式で、棒グラフやヒストグラム、散布図など一通り描画できる
  • ユーザーサイドから見ると、seabornと似たような感覚で使える

Bokehのいいところ

グラフは動的にいじれるし、見栄えも良い。HTMLとJavaScriptなので、Webアプリにも簡単に組み込める。

Bokehの悪いところ

ライブラリの性質上、データはPython側で用意し、描画のコードを書くのだが、実際にはJavaScriptにコンバートされることになる。 Python側のデータとJavaScript側のデータは必ずしも同一ではない(!)のに注意しないといけない。
400列の巨大データから、2行だけ使ってグラフを描画するケースなどもあるので、DataFrameを全てJavaScript側に流し込むわけにはいかない、という話だけど…



こんな感じでしょうか。 後は下にJupiter Notebookを貼っておきますので、マウスでいじってみて下さい。 (前回みたいにGistも用意したんですが、JavaScriptのロードでコケました…nbviewerだと動くのは、何でなんでしょうね?)

Jupyter Notebook Viewer

DPC入院料を月別/科別に可視化する

さて今日も元気にJavaScriptでガンガンフロントを書いていきましょう!
…という趣旨の記事を書きそうになって正気に返ったスタゲイラです。こんばんは。
えーと。ここしばらくはこんな本を読んでました。

Reactビギナーズガイド ―コンポーネントベースのフロントエンド開発入門

Reactビギナーズガイド ―コンポーネントベースのフロントエンド開発入門

このままだと、ブログが「日曜プログラマのWebサイト作り」になってしまうので、路線を戻します。
今回はSQLからは離れて、既に「DPC入院料」「科名」「診療月」が入ったデータセットがあるものと仮定し、簡単な可視化をやってみましょう。
使うのはpandasのプロット機能と、seabornです。
Jupyter Notebookをそのまま載せてみました。実務でも、大体こんな感じでやってます。

DPC入院料のグラフ化テスト

実務では月別の推移を見ることが多いです。
そして、大雑把に「今月は入院料が高い」「今月はなんか低い」と分かったら、そこから細かく見ていくわけですが、真っ先に切り分けるのは診療科であることが殆どです。
このように時系列を折れ線グラフで描いたり、分布をヒストグラムや箱ひげ図で確認するのはとても重要です。 分布に異常がないかヒストグラムでチェックして、箱ひげ図で異常値がないか見る感じですね。
最後に外れ値除去を行って再び箱ひげ図を見る、なんてこともやってます。

なんでPythonでGUIアプリを書かないの?

さて、前回はElectronを使ってでっち上げたアプリケーションを公開しました。
ElectronはJavaScriptベースのライブラリです。私が普段使っているのはPythonで、JavaScriptはロクに分かっていません。
が、いざデスクトップアプリを書く段になって、選択したのはElectronでした。

PythonGUIライブラリを使わない理由は?

当初は、PythonGUIライブラリを覚えるべきだ、と思っていました。代表的なものとして、PyQtとKivyがあります。
早速いじってみたのですが、どちらも「テーブルを表示する」というだけのことが、妙に複雑になっていて好きになれませんでした。
例えば、テーブルのデータを変数dfに格納したとします。
Pandasでhtmlテーブルを作るのは、df.to_html()というメソッド1行で事足りてしまいます。
PyQtでの実装は、えーと、StackOverFlowによるとこうみたいですね。
???うーん…???
QtCore.QAbstractTableModelを継承したPandas表示用のクラスを作成し、そこにデータを流し込むみたいです。ほ、ほほう・・・
もちろん、この辺の情報は全て公式の英語ドキュメントをきっちり読み込まないといけません。
Kivyだと、うーん、recycleviewなるものを使いみたいですね。英語のドキュメントを読みましょう。

他の言語を見てみると…

ちなみに同じことをScala-swingで実装すると、まあ、最初からテーブル用のモデルがあるので、大して苦労せず実装できます。
まー、こっちはこっちで英語のドキュメントなのは変わらないんですが、swingそのものが用途に向いているんでしょう。
本来このような用途に最も向いているのは、間違いなくC#ですが、今更新たな言語と格闘する時間もありませんでした。

結局HTMLが簡単だ

まー、UI部品を組み立てていくなら、HTMLが断然簡単ですね。
見た目はCSSで幾らでも変えられるし、プレビューはブラウザですぐ見れるし… Pythonでも、HTMLベースのGUIライブラリがあるといいんですけど。

DPCチェッカーElectron版を公開

今回はこちらです。 ZIPをダウンロードして解凍して、dpc.exeを叩いて下さい。ブラウザではなく、ちゃんとアプリケーションが走る筈です。 何だか一ヶ月ほど前に、「Windows版を作りました!」と自慢げにエントリ書いてますが、ええと、忘れて下さい。
前回のはかなり試験的なリリースで、何せファイルサイズは展開後で400MB超、exeを叩くとまずDOS窓が開き、続いてブラウザが開くという「すわ、マルウェアか!?」という挙動をしてました。
幾ら私がいい加減でも、「うーん、これアプリケーションの体を成してないよね・・・」というくらいには思います。

Electronを使ったWindowsアプリの開発について

Electronはウェブサイトをそのまんまデスクトップアプリにしてしまうライブラリです。
最近、とうとう日本語で書かれた解説書も出版され、これから盛り上がることは間違い・・・ないんじゃ・・・ないかなあ・・・(尻すぼみ
今回はズルをしていて、PythonのFlaskとよく似たライブラリ、expressでベタ移植をやってます。なのであんまり、本来のElectronの書き方ではないです。実装方法についてはあんまり参考にしないで下さい。

これからの課題は?

えーと、Python版は一時停止することになると思います。
理由は簡単で、PythonGUIライブラリを使って、アプリケーションを作る自信が無いからです。 (これについては別エントリで詳述します)
PythonにはPyQt / Kivyといった有名なGUIライブラリがありますが、結論から言うとNode.js覚えた方が早いですね!(白目
本格的なウェブサイトや複雑なアプリケーションの構築ならいざ知らず、こういう軽量アプリなら、下手に複雑なライブラリを覚えるより、別言語で書いた方が早いと言うことは往々にしてあります。
ただ、フロントをElectronにして、バックエンドでPython走らせる方法もあるので、高度な分析機能を実装するならPython版を持ち出すかも・・・?
そこまで高度な機能なら、正直、ツールにしても仕方ない感じがしますが、まあ予定は未定ってことで・・・