Edited at

jupyter(Daru) と ActiveRecord@rails の連携をとても簡単にする機能(ActiveRecord::Relation#to_df)を書いた


TL; DR

jupyter_on_railsGemfile に追加すると、 ActiveRecord::Relation#to_df が使える。

includes などもよろしく対応する。

irb(main):002:0> Article.to_df

Article Load (0.5ms) SELECT `articles`.* FROM `articles`
=> #<Daru::DataFrame(2x3)>
id title body
0 1 hello worl This is an
1 2 jupyter on With Activ

irb(main):003:0> Article.includes(:comments).to_df
Article Load (0.4ms) SELECT `articles`.* FROM `articles`
Comment Load (41.5ms) SELECT `comments`.* FROM `comments` WHERE `comments`.`article_id` IN (1, 2)
=> #<Daru::DataFrame(3x7)>
id title body comments.i comments.c comments.b comments.a
0 1 hello worl This is an 1 John Smith Hello, too 1
1 1 hello worl This is an 2 Taro Yamad Nice to me 1
2 2 jupyter on With Activ nil nil nil nil

irb(main):004:0> Article.where(id: 1).to_df

Article Load (0.5ms) SELECT `articles`.* FROM `articles` WHERE `articles`.`id` = 1
=> #<Daru::DataFrame(1x3)>
id title body
0 1 hello worl This is an

jupyter 上だと:

スクリーンショット 2019-03-04 23.26.49.png


本文


Motivation

Rails + Jupyter で操作を行なっていると、 ActiveRecord -> Daru への連携が、うまくいかないのでちょっと悲しい。

せっかく、 Rails には ActiveRecord::Relation という、 DataFrame っぽいデータ構造があるのだから、それをさくさくと DataFrame に変換してほしいと思った。

Daru には Daru::DataFrame.from_activerecord メソッドがあったが、 rails 的にはどう考えても #to_df したかった。 (そして、 includes とかをうまく扱ってくれなかったりしたのが辛かった)


実装


  • ActiveRecord::Base に対して(#to_df)メソッドを追加する。


    • 結果、 ActiveRecord::Relation から呼べる




  • includes/eager_load/preload している association があれば、それもまとめて df にする。


使い方

依存関係に jupyter_on_rails を追加するだけ。


Gemfile

gem 'jupyter_on_rails'


以前の記事で紹介した通り、この gem からだと jupyter + rails の連携が簡単にできるので、 jupyter の起動はそれでやるのがおすすめ。

その場合の gem/コマンド


Gemfile

gem 'jupyter_on_rails'

gem 'ffi-rzmq'

bin/rake jupyter:notebook


所感

これで生産性が大きく向上するはず。