読者です 読者をやめる 読者になる 読者になる

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

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

Pythonでのデータ可視化について色々

Pythonでグラフを描こうと思ったら

まあ、普通はmatplotlibですね。
matplotlibは事実上のデファクトであり、これで困ることはまずありません。以上、今回はこれで終わり・・・
というわけには行きませんね。他にも幾つかの選択肢がありますので、見ていきましょう。

seaborn

seabornはmatplotlibをベースに構築されたグラフライブラリです。
matplotlibのスタイルはいかにも「研究論文に載せてください!」というものですが、seabornはもうちょっと洗練された見た目になります。
「あんまりスタイルをいじってる時間は無いけど、綺麗なグラフが欲しい」という時に重宝しますね。
また、matplotlibとseabornをimportしてグラフを描くと、自動的にseabornのスタイルが適用されます。単にmatplotlibのグラフを綺麗に描画したい、というときにもいいでしょう。
が、それだけに使うにはちょっと勿体ないというか、オーバーキル気味のライブラリでもあります。
heatmapの例を見れば分かるとおり、ゴリゴリの理系論文で使いそうなライブラリで、出自や想定される用途はmatplotlibに近いんだろうなあ・・・

Pandas

なんとPandasにもグラフ描画機能があります!
ドキュメントを読めば分かるとおり、DataFrameのメソッドにplotがあるのです。やった!これで可視化の方法は決まりだ!
・・・と、なるかどうかはともかく、さっとグラフを描くにはとても便利です。
ちなみに実体はmatplotlibですので、勘違いしないように。

Bokeh

Bokehは期待の新星で、上の3つ(matplotlib/seaborn/pandas)とは全くの別系統です。
というよりは、上の3つか同一系統というのが正しいですが・・・ BokehはJavascriptベースの可視化ライブラリで、結果はHTMLファイルか、scriptタグで返ります。
Webアプリケーションに組み込むには非常に便利で、かつ書く分にはPythonで完結し、一行もJavaScriptを書かなくていいというお手軽さ。
Pandasとの相性もいいです。
問題点は、まだ荒削りなこと。バージョン0.9x系までは外れ値を含むデータを描画するとヒストグラムが壊れたりしました。
現行バージョンでも、データ量が多くなるとフリーズしたり、描画が変になったりすることがあります。

まとめ

matplotlib系統が返すのはグラフオブジェクトで、それをpngなりX11ウインドウなりで描画することになります。
ウェブアプリケーションなどに組み込むのであれば、Bokehの方が扱いやすいかも知れません。
一方、得体の知れないデータがあって、どんなメチャクチャな描画になってもいいから、とにかく一度グラフにして状況を見てみたい!というときは、seabornを使うのが無難でしょう。
Pythonを使ってデータ分析をする場合、そういうトライアンドエラーを繰り返すのが多いですので、普段使いにはseabornがオススメです。
Pandasから直接接続できるBIツールみたいのがあればいいんですけどね・・・

DPCチェッカー0.10 ダッシュボード機能を追加

例によってこちらです。

バージョン0.08の変更点:ダッシュボード機能

予告通りダッシュボードをつけました。
開くと科別・病棟別の出来高対比グラフ、また同じく科別・病棟別の収益分布がグラフで描画されます。
ネタが思いつけば追加は簡単なので、順次増やしていくつもりです。

ビジュアライゼーションについて

今回はC3.jsを利用させて頂きました。 こちらは有名なD3.jsのラッパーで、棒グラフや円グラフをある程度簡単に描画出来ます。
ただし、JSONを知らない界隈から来ると(私がそうです)、結構面食らいますね。
Pythonのグラフライブラリは殆どがPandasのDataFrameを想定しているので、一般的な表形式データ(即ちcsvのようなもの)を頭に浮かべればすぐ理解できます。
が、JavaScriptの世界で想定されているのはJSONです。頭の切り替えには結構苦労しました。

最初っからMatplotlibなりSeabornなり使えば楽なのですが、どちらも配布するにはフォントの問題があります。
具体的には、ユーザー側でフォントファイルの追加をしないと日本語が文字化けする筈です。
Pythonから使うにはダントツで簡単なんですけどね・・・

DPCチェッカー0.08 デザインをちょっと修正

例によってこちらからどうぞ。

バージョン0.08の変更点:デザイン修正

これを書いている人間は、残念ながら「デザイン」とか「絵心」というものは皆無です。
ということでGoogle様のMaterial Design Liteに乗っかりました。
といっても所々昔のままで、ツギハギ感がひどいですが、ドキュメント読み始めてまだ数時間なので…
しかしこういうデザインテンプレートがオープンソースで山ほど転がってるのが、Web技術のいいところです。
デスクトップ向けのUIだと、あんまりこういうのは見つからないので…

次回アップデートではようやくグラフ描画機能を追加する予定です。
Flaskの勉強もちょこちょこしてますので、各種の挙動がもう少しマシになると思います。

SQL方言について(ついでにDPCチェッカーにクエリを追加)

SQLの方言

残念なことですが、SQLは実装ごとに方言があります。
私はPostgreSQLばっかりいじってたので気にも留めていませんでしたが、今回DPCチェッカーを作っていて否が応でも気付かざる得ませんでした。
DPCチェッカーは組み込みで配布するため、SQLite3を使っています。exe単体で実行できるSQLで、Pythonには何とビルトインされています。
こちらの実装はPostgreSQLとかなり違っていて、例えば日付データをネイティブで扱うことが出来ません。
そこにさえ目をつむれば、大抵のクエリは走るのですが、今回はここで詰まりました。

select データ識別番号,実施年月日,診療明細名称,SUM(明細点数・金額*行為回数) 
from etable
Where データ区分 = 60 
AND (データ識別番号,実施年月日) IN (select データ識別番号,実施年月日 from dtable Where データ区分 = 93) 
group by データ識別番号,実施年月日,診療明細名称
HAVING SUM(明細点数・金額*行為回数) > 0;

以前このブログで紹介した、DPC期間中に行った検査を探すクエリです。 INを使った相関サブクエリで、「Dファイル上でDPC入院料を算定した患者と日付」に条件に絞る、ということをやっています。
このクエリはPostgresでは走りますが、SQLiteでは走りません。 AND (データ識別番号,実施年月日) IN...の部分が問題です。
これをAND データ識別番号 IN...とすると走ります(これでは条件を満たしませんが)。
()でカラムを複数指定するやり方は、行値式というそうで、実装されているSQLは限られています。 (メジャーどころでは、MicrosoftSQL Serverも対応していないとか)
どんなに頭を悩ましたところで、実装されていないものは走りません。書き方を変えます。

select e.データ識別番号,e.実施年月日,e.診療明細名称,SUM(明細点数・金額*行為回数) 
from etable AS e
Where データ区分 = 60 
AND EXISTS (select d.データ識別番号,d.実施年月日 from dtable Where データ区分 = 93
AND dtable.データ識別番号 = etable.データ識別番号
AND dtable.実施年月日 = etable.実施年月日)
group by e.データ識別番号,e.実施年月日,e.診療明細名称
HAVING SUM(明細点数・金額*行為回数) > 0;

今度はEXISTSを使いました。意味合いは違いますが、求める結果は同じです。
Postgresでは走りますので、意気揚々とSQLiteで走らせると・・・答えが返ってきません。
どうやら私がやっつけで書いたクエリに問題があって、Postgresが優しく(見えないところで)始末をつけてくれたのでしょうか。それとも、SQLiteのEXISTS実装にパフォーマンスの問題があるのでしょうか。または、その両方?
前者である可能性が高いですね。 さて困りました。もうちょっとEXISTSについて調べてもいいのですが、手っ取り早いのは以下のクエリです。

WITH d93 AS (select データ識別番号,実施年月日 from dtable Where データ区分 = 93),
e60 AS (select データ識別番号,実施年月日,診療明細名称,SUM(明細点数・金額*行為回数)  AS 出来高金額
from etable
Where データ区分 = 60 
group by データ識別番号,実施年月日,診療明細名称
HAVING SUM(明細点数・金額*行為回数) > 0)
select d93.データ識別番号,d93.実施年月日,e60.診療明細名称,e60.出来高金額
from d93
INNER JOIN e60
USING(データ識別番号,実施年月日);

WITH句でテーブルを2つ作ってINNER JOINでくっつけています。
結局、今回やりたいのは「検査を行った患者とその日付」の集合と、「DPC入院料を算定した患者とその日付」の積を求めること、つまり二つの集合の共通集合を導き出すことです。
ならばINNER JOINで良いわけですね。

(ちなみに、上記のクエリは検査版と注射版を作って、DPCチェッカーに追加しておきました)

DPCチェッカー0.07 : 外部クエリの読み込みに対応しました

例によってこちらからどうぞ。

バージョン0.07の変更点:外部クエリの読み込み機能について

今まで当ツールはコード内部にそのまんまSQLクエリが書いてあるというシロモノでした。
拡張性もへったくれもありませんので、バージョン0.07でSQLクエリは本体から切り離し、queryフォルダに置く形式となっています。
その副産物で、外部クエリの読み込みにも対応出来ました。
お好きなSQL文をqueryフォルダにtxtで置けば、メニューに選択肢が増えます。
なお、エンコーディングUTF-8にして下さい。

あと幾つかのクエリを追加してあります。 当ブログでも紹介してきましたが、

  • EF/Dファイルの区分別集計
  • 手術のカテゴリ別金額
  • 副傷病分岐なしチェック

です。 本来ならばDPC中に行った検査/注射のチェック機能も追加する筈でしたが、当該のクエリがSQLiteで走りません・・・
移植にはもう少しかかりそうですので、気長にお待ち下さい。
(この件で「SQLクエリの移植」というひどい問題にも出会いました。これは追々記事にします)

今後の課題と予定

見た目がひどい

ほんとにひどい。見づらい。
ということで、多分レイアウト修正をやります。ついでにbootstrapでも勉強するつもりです。

ビジュアライゼーション

かっこいい分析機能とかあるといいですね。こう、どかーんとダッシュボードが開いて、グラフがぬるぬるっとアニメーションして描画されるようなの。
すごい適当なことを書きましたが、こういう機能を楽に実装するなら、もうJavaScriptのライブラリを使うしかありません。
(このブログで紹介したBokehはPythonで動くグラフを作れますが、出力結果はJavaScriptです)
このツールがウェブアプリなのは、私がC#に挫折しただけではなく、グラフ描画にまつわる問題もあるのでした。
まあ、D3.jsみたいなのは他にありませんしね。

DPCチェッカーを0.06にアップデートしました

といっても、csvエクスポート機能をつけただけですが…
例によってこちらからどうぞ。
今後の予定としては

  • さっさと外部クエリ読み込みを実装する
  • というか今までブログに上げてきたクエリを整理してGitHubにまとめる
  • Bokehを使った可視化は業務でやってるので、早めに組み込む

となっております。
如何せん片手間仕事なのでペースは遅いですけど。

もし時間があれば、ロジックをそのまんま流用してJavaScriptで書き直し、Electronでアプリ化したものを配布したいですが、うーん。
今の状況だと難しそうです。
ちなみにPyinstallerを使えば、Pythonのままでexeに出来るのですが、様々なライブラリを全てバンドルしてしまうようで、500MB超にまで膨れ上がります。ソースのサイズを考えると無駄があり過ぎますね。

DPCチェッカー 0.05を公開しました

DPCチェッカー 0.05

いきなりですが、業務の片手間にツールを作ったので公開します。
こちらからどうぞ。 DPCチェッカーはEF/Dファイルを読み込み、出来高対比を算出したり、退院時処方のエラーチェックを行うソフトです。
Flask/Pandas/SQLite3で実装されたウェブアプリケーションで、ブラウザ上で動作しますが、実際にはローカルで動いています。
(初回起動時に、dpc.dbというDBファイルを作成し、そこにデータをストアする仕組み)

こんなのを作ろうと思った経緯

私は普段のDPC分析業務の殆どを、Jupyter Notebook上で行っていますが、それだと他の人が困るかなーと、ここ数ヶ月ぼんやり考えていました。誰でも使えるGUIがあるといいよね、と。
この数週間はすごく調子に乗っていて、「ちょっとC#かじってアプリをでっち上げよう!」と意気軒昂でしたが、うん、これ、そんな簡単なもんじゃないですね…SQLiteのドライバの挙動とか、C#の言語仕様とか、WPF(Windows Presentation Foundation、Visual C#GUIアプリケーションを作るときの枠組みのひとつ)とかと1週間ちょい格闘した後、ふと我に返りました。

これ、完成しないんじゃね?

偉い人は言いました。「たぶん動くと思うからリリースしようぜ」と。
私の技術では動くところにすら到達出来ません。さっさと諦めて、いつも使っているPythonでWebアプリケーションにすることにしました。
こっちはプレゼン目的にでっち上げたこともありますので、すぐに作れます。
今、Jupyter Notebookでやっているデータの可視化や、このブログで書き殴ってきた様々なクエリ発行も、このアプリケーションに纏めていこうと考えています。

ちなみにGit Hubを使うのはこれが初めてで、ろくに使い方がわかってません。色々ヘンテコなところがあると思いますがご勘弁ください。
ツールの中身については…はい、ひどいシロモノです。色んな修正点が必要になると分かっています。
「なんてひどい!こんなの書き換えてやる!」と思った方は是非そうしてください。当然改変・再配布・利用フリーです。