どうも、Androidアプリの開発をやっています、エンジニアの岩木(@YusukeIwaki)です。
社内ではRubyistたちに囲まれながら、孤独にJavaを書いています(誇張w)
クラウドワークスでは、施策の事前調査や効果検証などのデータ測定を、エンジニアが率先しておこなう開発プロセスをとっています。
データ収集ではSQLを使う機会が多いのですが、「会員登録した人の、1週間単位での発注率の推移」のような複雑なデータを取ろうとした時に、わりとつらい思いをすることが多かったため、SQL運用のつらみを解決すべくPandasとJupyterの布教活動をおこなった!という話を共有します。
そもそも解決したかった"SQLのつらみ"
「データ収集をいろんなエンジニアがやる」というシーンにおいて
クエリの結果の再利用性が低い
「よく使うベースクエリは関数化して、みんなで使い回す」ということができない。同じクエリをコピペして使わないといけない...
デバッグしづらい
ブレイクポイントを張る、とか途中経過の値を見てみる、などはできないので、毎回クエリが走り切るのを待たないといけない…
というSQL二重苦が、わりと深刻で解決したいなぁと思っていました。
#実際に、「うぉぉおお〜」「くっそー!」と叫んでいるエンジニアが私の周りでもちらほらいましたw
2000万行のテーブル相手に「このクエリで正しく取れるかなぁ」と毎度4分くらいずつ待たされる、みたいな経験をしたことがある方も多いのではないでしょうか。
手元で必要なデータをとるだけならともかく
といった"運用"を始めると、
→ SQL職人しか読めない書けない
→ 技術的負債ので・き・あ・が・り・♪ \(^o^)/
→ 読めないSQL触るの怖いから、新しくSQL作るか・・・(おい
のように、どんどん「データ測定」の本質からはずれていってしまいますよね。
Pandas
Pandasとは、Pythonでデータ分析を行うためのライブラリです。
Pandasを使うことで、3つの観点で「ラク」ができるようになります。
デバッグ負荷の軽減
Pandasを使って、SQLサーバから取ってきたデータ列を変数に入れてしまえば、あとはJOINするのもGROUP BYするのもORDER BYするのも、手元のマシンでオンメモリで動かせます。
そのため、マシンリソースさえ潤沢にあれば「いちいちクエリの結果を4分待つ」ということが一気に減り、デバッグがはかどります。
一部のクエリの簡略化
SQLで煩雑化しやすい「各発注者が"一番最初に"発注した仕事」みたいなクエリは、
pdJobs = read_sql(''' SELECT * FROM jobs WHERE status = 'contracted'; ''', db) pdJobs.groupby("user_id").first()
のようにスッキリ書くことができます。
整形がとにかく楽
SQLでは、データセット(モデル)とCSV(ビュー)は密結合していて、整形のためにもSQLをつかってゴリゴリやる必要がありましたが、
Pandasでは、データセットとビューは疎結合なので、
- データの一部を抽出してグラフを書いたり
- 表をいくつかまとめて定期的にPDF出力したり
- プレーンテキストでSlackに投稿したり
などが簡単におこなえます。
これは、「運用」をする上で非常に有用で、 下記のように「毎朝何かのデータを定期的に観測する」といったことをカジュアルに実現するには、非常に適していると思います。
Jupyter Notebook
Pandasは単体でも便利なのですが、データ分析では2次元データ(表形式のデータ)を扱うことが多いので、スクリプトをデバッグするのが案外大変です。
そこで、Jupyter Notebookを利用することで、スクリプトの動作を随時みながらデータ解析ができ、さらに分析が"ラク"になります。
Jupyterはひとことでいうと、 Webベースの超リッチなコンソール です。もしMathematica使ったことがある方だったら、それに近いものだと想像していただければよいかと思います。
Pandas単体のスクリプトを動かすのと違い、Jupyterはサーバプロセス(正確にはカーネル)を落とさないかぎりデータ列はオンメモリで保持されるので、Jupyterを適当なサーバに入れておくことで
- 昨日途中までとったデータで今日続きをやる
- Aさんがやってつまづいたデータ取得のつづきをBさんがやる
といったこともできるようになります。 データ分析は一筋縄で行かないことのほうが多いので、こういった特性は非常に便利です。
また、Jupyterでは .ipynb
という独自の拡張子(といってもGitHubでは標準で見られる!)のファイルが作業ファイルとして生成されますが、
jupyter nbconvert --to python hogehoge.ipynb --stdout > hogehoge.py
jupyter nbconvert --to html --ExecutePreprocessor.enabled=True --ExecutePreprocessor.timeout=3000 hogehoge.ipynb --stdout > hogehoge.html
で、下記のようにHTML化してデータ導出過程もふくめてデータ分析結果を配布をしたり、レビュー材料にしたり、
などなど、エクスポートの仕方を工夫することで、様々な活用ができるはずです。
「布教」活動
さて、技術的な面に関しては今まで挙げたとおりなのですが、いくらPandasやJupyterが便利と自分が思っていても、 それが組織にとって役に立つかはわかりませんし、周りの人が納得して利用しなければ、意味がありません。
社内のエンジニア全体に広めるための活動として
- エンジニア全員に「とりあえず勉強しよう!」と講習をする
- 週次勉強会で発表をする
などは、大切な機会なんですが、 いっぽうで、使命感がない中で話を聞くだけでは「あぁすごいねー」で流されてしまうリスクもあります。
そこで、まずは確実にデータ分析で困っているであろう同じチームのエンジニアから「こりゃ便利だ!すげぇ」と感動を共有することを第一目的に、 "じんわりと 広めていく"ことにしました。
セットアップ手順を「コマンドを順番に打つだけ」レベルに記載
SQLで「うわぁぁああ」「くっそーー」と発狂しているエンジニアに「これインストールして」ってお願いするわけですから、 no such command: jupyter
みたいなのが出てくると、それだけで感動はなくなりますね。
社内のブログで記事を書いておき、誰でもコメントができる状態にしておきました。
環境セットアップはチームメンバー全員で時間枠を1時間とって実施
pdJobs = read_sql(''' SELECT * FROM users LIMIT 10 ''', db);
のような至極簡単なクエリをPandasで実行できるようになるまでのセットアップを、時間枠を決めて実施しました。
「ブログに書いてあるのでやっておいてね」で大丈夫な人にとっては1時間は暇かもしれませんが、 チームなので困っている人がいたら積極的に助け合わないといけません。
実際に、自分のチームと隣のチームでそれぞれ時間を取って実施してみたところ、単純に環境セットアップしただけでなく
こんなかんじのフィードバックコメントがもらえたりもして、意図を説明して対話しながらセットアップする機会の重要さを改めて実感しました。
「Made by Pandas&Jupyter」なものをチラ見せする
百聞は一見にしかず。JupyterとPandasを使ってグラフ出力などをすると、見た目的に派手なので、
みたいに日頃からチラ見せを繰り返していると、「あのときのグラフってどうやって出しているの?」といった質問が来て、Pandasの布教の機会となります。
また、PandasはDataFrameの扱いに慣れるまでは、実際に動かしている人に習うのが効率がよく、 そういう意味でも、実際に動かしているものを見せ合うということは、一石二鳥だったりするのです。
で、布教活動の結果はどうだったの?
とりあえずエンジニアのなかでは4分の1くらいの人が「熱狂的に使うようになった」「ツールとして使えるようになった」という感じで、"意外と広まったぁ"とおもいます。
とはいえ、4人に1人しか使えないのだと微妙なので、今後は地道に全体の半分くらいまで広めていきたいと思っています。
We are hiring!!
クラウドソーシングのクラウドワークスでは、データ分析の仕組みやインフラを構築・改善できるエンジニアを募集しています! また、アプリとかAPIとかガンガン開発したいよ、というエンジニアもWelcomeです!