LoginSignup
35
33

More than 5 years have passed since last update.

Ruby で数値を弄るやーつ -- Daru について --

Last updated at Posted at 2015-12-17

背景

先日、RubyKaigi 2015 に参加してきました
終了後、↓のような感想エントリを読んで、そうだよなーと思いました

RubyKaigi 2015(3日目) ただのにっき

ところで今回のRubyKaigiで「あ、これはまずいな」と思ったことに「機械学習系の発表がひとつもなかった」点がある。昨日のパーティでも話題にあげてみたところ、危機感を抱いている人は少なからずいた印象だけど、根っこをたどると数値演算ライブラリの整備をずーっと放置してきたことがあるだろう。気がつくと数値演算方面ではPythonに大きく水をあけられていて、いまやその応用である機械学習では(LLの中では)Pythonの独壇場だ。Webアプリケーションの分野で一世を風靡した気になってる間に、いま一番ホットな領域がまったく話題にならない言語になってしまった。

というわけで、Ruby でデータセットを弄る Gem ってのが無いわけではないので、ひとまず触ってみて、アドベントカレンダーでシェアしたら良いかもなーと思ってこのエントリを書いています

Daru

先々日、SQL 脳から見た Ruby という発表をしたところ「タプルの集合っぽいのを弄るなら Daru という Gem あるから触ってみると良い」とアドバイスを頂きました

daru (Data Analysis in RUby) is a library for storage, analysis, manipulation and visualization of data.
daru is inspired by pandas, a very mature solution in Python.

Daru はデータを解析したり、弄ったり、可視化したりする、Python の Pandas インスパイアの Gem だそうです

インストール

gem i daru ってするだけでインストールは出来るんですが、

*************************************************************************
Thank you for installing daru!

  oOOOOOo 
 ,|    oO
//|     |
\|     |
 `|     |
  `-----`


Hope you love daru! For enhanced interactivity and better visualizations, 
consider using gnuplotrb and nyaplot with iruby. For statistics use the 
statsample family.

Read the README for interesting use cases and examples.

Cheers!
*************************************************************************

とか出てきて、ほっこりしますね

つかいかた

扱えるデータ

Data structures:
Vector - A basic 1-D vector.
DataFrame - A 2-D spreadsheet-like structure for manipulating and storing data sets. This is daru's primary data structure.

1次元のベクトルと、2次元のスプレッドシートげな構造を扱えますとありますね

1次元のベクトル

  • 1 から 10 まで、みたいなデータ
require 'daru'

vec = Daru::Vector.new([*1..10].map { |x| x * 99 }, index: [*1..10], name: 'ninetynine')

#=> #<Daru::Vector:70313282595960 @name = one to ten @size = 10 >
#=>            ninetynine
#=>          1         99
#=>          2        198
#=>          3        297
#=>          4        396
#=>          5        495
#=>          6        594
#=>          7        693
#=>          8        792
#=>          9        891
#=>         10        990

vec[1]
#=> 99

vec[3]
#=> 297

vec[1..3] # range を渡すと Vector の index じゃなくて添字扱いなの...
#=> #<Daru::Vector:70313320646980 @name = ninetynine @size = 3 >
#=>            ninetynine
#=>          2        198
#=>          3        297
#=>          4        396

2次元のベクトル

  • A から Z までの文字と、番号、みたいな
df = Daru::DataFrame.new(
  {
    char: [*'A'..'Z'],
    num: [*1..26]
  }, 
  index: [*'a'..'z'],
  order: [:num, :char]
)
#=> #<Daru::DataFrame:70313283713820 @name = afe2e697-c235-469a-9b8d-b3189dd438b8 @size = 26>
#=>                  char        num 
#=>          0          A          1 
#=>          1          B          2 
#=>          2          C          3 
#=>          3          D          4 
#=>          4          E          5 
#=>          5          F          6 
#=>          6          G          7 
#=>          7          H          8 
#=>          8          I          9 
#=>          9          J         10 
#=>         10          K         11 
#=>         11          L         12 
#=>         12          M         13 
#=>         13          N         14 
#=>         14          O         15 
#=>        ...        ...        ...

df[:char][3..6]
#=> #<Daru::Vector:70313282764340 @name = char @size = 4 >
#=>      char
#=>    d    D
#=>    e    E
#=>    f    F
#=>    g    G

df.row['a']
#=> #<Daru::Vector:70313321157180 @name = a @size = 2 >
#=>         a
#=>  num    1
#=> char    A

df.row['a'..'c']
#=> #<Daru::DataFrame:70313321055320 @name = 81e720bf-41a7-4077-8ddc-ec2f7b38fb12 @size = 3>
#=>                   num       char 
#=>          a          1          A 
#=>          b          2          B 
#=>          c          3          C 

おまけ

df.to_s
#=> "<table><tr><th colspan=\"3\">Daru::DataFrame:70313279396300  rows: 26  cols: 2<tr><th></th><th>num</th><th>char</th></tr><tr><td>a</td><td>1</td><td>A</td></tr><tr><td>b</td><td>2</td><td>B</td></tr><tr><td>c</td><td>3</td><td>C</td></tr><tr><td>d</td><td>4</td><td>D</td></tr><tr><td>e</td><td>5</td><td>E</td></tr><tr><td>f</td><td>6</td><td>F</td></tr><tr><td>g</td><td>7</td><td>G</td></tr><tr><td>h</td><td>8</td><td>H</td></tr><tr><td>i</td><td>9</td><td>I</td></tr><tr><td>j</td><td>10</td><td>J</td></tr><tr><td>k</td><td>11</td><td>K</td></tr><tr><td>l</td><td>12</td><td>L</td></tr><tr><td>m</td><td>13</td><td>M</td></tr><tr><td>n</td><td>14</td><td>N</td></tr><tr><td>o</td><td>15</td><td>O</td></tr><tr><td>p</td><td>16</td><td>P</td></tr><tr><td>q</td><td>17</td><td>Q</td></tr><tr><td>r</td><td>18</td><td>R</td></tr><tr><td>s</td><td>19</td><td>S</td></tr><tr><td>t</td><td>20</td><td>T</td></tr><tr><td>u</td><td>21</td><td>U</td></tr><tr><td>v</td><td>22</td><td>V</td></tr><tr><td>w</td><td>23</td><td>W</td></tr><tr><td>x</td><td>24</td><td>X</td></tr><tr><td>y</td><td>25</td><td>Y</td></tr><tr><td>z</td><td>26</td><td>Z</td></tr></table>"

なぜ to_s すると HTML 出てくるの... 何それ怖い

SQL っぽい操作

絞り込み

df.where((df[:num].eq(5) | df[:num].eq(6) | df[:num].eq(7)) & df[:char].eq('G'))
#=> #<Daru::DataFrame:70324863177360 @name = 49f9f681-c475-4e37-aab3-613e0d8050f9 @size = 1>
#=>                  num       char 
#=>         g          7          G 

グルーピング

df = Daru::DataFrame.new(
  age:  [19, 18, 22, 45, 36, 60],
  from: %w[東京都 埼玉県 東京都 東京都 神奈川県 千葉県],
  name: %w[太郎 花子 二郎 フランソワーズ としあき たもつ]
)

#=> #<Daru::DataFrame:70324885066340 @name = 6b7e37b3-ba86-4bf2-8b0e-d4052addd62b @size = 6>
#=>                   age       from       name 
#=>          0         19        東京都         太郎 
#=>          1         18        埼玉県         花子 
#=>          2         22        東京都         二郎 
#=>          3         45        東京都    フランソワーズ 
#=>          4         36       神奈川県       としあき 
#=>          5         60        千葉県        たもつ 

df.group_by(:from)
#=> #<Daru::Core::GroupBy:0x007feb92952dd0
#=>  @context=
#=>   
#=> #<Daru::DataFrame:70324885066340 @name = 6b7e37b3-ba86-4bf2-8b0e-d4052addd62b @size = 6>
#=>                   age       from       name 
#=>          0         19        東京都         太郎 
#=>          1         18        埼玉県         花子 
#=>          2         22        東京都         二郎 
#=>          3         45        東京都    フランソワーズ 
#=>          4         36       神奈川県       としあき 
#=>          5         60        千葉県        たもつ 
#=> ,
#=>  @groups={["千葉県"]=>[5], ["埼玉県"]=>[1], ["東京都"]=>[0, 2, 3], ["神奈川県"]=>[4]},
#=>  @non_group_vectors=[:age, :name]>

SQL で書きたい...

プロットとか色々...

こっからが本番... だけど、ひとまずここまで。続きはまたこんどということで
この辺のデモを試したかったのですが、plot を動かすための条件がまだ分かってません

感想

  • いくらなんでも生の2次元配列をゴリゴリ弄っていくのは辛いよなと思っていたので、こういうライブラリがあるのはありがたい
  • SQL でやったほうが柔軟性あるし楽なんじゃないの。と思うけど、あえてこういうのがある理由というのがあるはずなので、それを探りたい
  • Python の Pandas との違い(主に、なにがどれくらい足りないかなど)も分からないので Pandas と併せて今後も触ってみたいところ

参考資料

35
33
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
33