はじめに
- 昨日Vaexの性能評価の記事を書きました。
- その記事では長くなってしまうので基本的な使い方などを省略しました。
- なので今回は入門記事として使い方を紹介します。
Vaexとは
昨日の記事でも書きましたが、遅延評価/Pandasライク/アウトオブコアという特徴を持ったデータフレームライブラリです。 github.com
リンク集
- ドキュメント: https://docs.vaex.io/en/latest/index.html
- ライブラリ作者解説記事①: Vaex: Out of Core Dataframes for Python and Fast Visualization
- ライブラリ作者解説記事②: Vaex: A DataFrame with super-strings – Towards Data Science
インストール・読み込み
インストールはpipやcondaを使って通常通り行えます。
pip install vaex
読み込みもライブラリ名のままimportすればOKです。
import vaex
読み込み
それでは早速使っていきましょう。
df = vaex.example()
vaex.example()
を呼ぶと、テストデータ(http://vaex.astro.rug.nl/data/helmi-dezeeuw-2000-10p.hdf5)をダウンロードして読み込んでくれます。
遅延評価なライブラリなので、データを読み込んだといってもメモリに乗せているわけではなく、一瞬で読み込みは終わります。
表示
そのままdataframeをそのまま打ち込むと一部表示できます。
df
これはデータをすべてメモリに乗せているわけではないので、一瞬で表示されます。
同じアウトオブコアライブラリのDaskだと一部表示するために dask.dataframe.head()
などで呼び出して表示までにだいたい数秒かかるのでそれに比べるとUXとしてかなり良いです。
カラムはPandasと異なりOrderedDict型になっているので次のような形で確認できます。
df.columns.keys()
# => odict_keys(['E', 'FeH', 'L', 'Lz', 'random_index', 'vx', 'vy', 'vz', 'x', 'y', 'z'])
カラムを選択して表示する場合はPandasと同じようにできます。
df.x # df['x']も同じ # Expression = x # Length: 330,000 dtype: float64 (column) # --------------------------------------- # 0 -0.777471 # 1 3.77427 # 2 1.37576 # 3 -7.06738 # 4 0.243441 # ... # 329995 3.76884 # 329996 9.17409 # 329997 -1.14041 # 329998 -14.2986 # 329999 10.5451
ただこれも遅延評価なので全てがメモリに乗っているわけではありません。
評価・仮想関数
もし評価を行いたい場合は evaluate()
を使います。次のような感じです。
df.evaluate(df.x)
# array([ -0.77747077, 3.77427316, 1.3757627 , ..., -1.14041007, -14.2985935 , 10.5450506 ])
evaluate()
はカラムだけでなくnumpyの多くの関数でも使えるらしいです。
import numpy as np exp = np.sqrt(df.x**2 + df.y**2 + df.z**2) df.evaluate(exp) # array([ 2.96554504, 5.77829281, 6.99079604, ..., 8.86425027, 17.60104719, 14.54018152])
np.sqrt(df.x**2 + df.y**2 + df.z**2)
はこの時点では評価されないので、Vaexでは「仮想関数」と呼びます。次のようにカラムに仮想関数を入れることもできます。
df['v'] = np.sqrt(df.x**2 + df.y**2 + df.z**2) df[['x', 'y', 'z', 'v']]
選択
データの選択は select()
を使って行います。 select()
はcopyを行わないのでメモリを増やすことなくデータを選択できます。
df.select(df.x < 0) # xが負なものだけ選択 df.evaluate(df.x, selection=True) # array([ -0.77747077, -7.06737804, -5.17174435, ..., -1.87310386, -1.14041007, -14.2985935 ])
Pandasライクな書き方もできるらしいです。
こちらもcopyが発生しないので、これで十分な気もしますが、 select()
の方が嬉しいケースもあるのかもしれません。
df_negative = df[df.x < 0] df_negative[['x', 'y', 'z', 'r']] # xが負なものだけ表示
※追記 ライブラリ開発者のMaarten A. Breddelsから直接DMもらいました。許可をもらったのでここに掲載します。(Thank you so much!)
ざっくり言うと、性能面では差がないのですが、dfが大量にできるのを防げたりプロットするときにselectionありとなしで簡単に比較できるとのことです。
統計処理
統計処理も並列化処理を使って高速に行えます。大体Pandasと同じAPIのようです。
df.count() # array(330000.) df.mean(df.x) # -0.06713149126400597 df.mean(df.x, selection=True) # -5.211037972111967
さらに細かいAPIはドキュメントを参照してください。
可視化
Vaexの素晴らしいところは集約関数を伴う可視化メソッドも並列化処理が行われ、単純にmatplotlibを使うより高速に描画できる点です。APIはPandasに似ていますが若干違うので注意です。
ax, = df.plot1d(df.x, linewidth=5) # 返ってくるのがline2Dの配列なので注意 # ↓はグラフの見た目調整 ax.axes.tick_params(axis='both', labelsize=20) ax.axes.xaxis.label.set_size(20) ax.axes.yaxis.label.set_size(20)
これはxでgroupbyしてカウントしたもののヒストグラムです。
もし、ヒストグラムでなく別の集約関数を扱いたい場合は、 plot1d(df.x, what='method_name(col_name)')
のように what
引数を使います。例えばxの平均を出したい場合は次のようになります。
# xでgroupbyしてEの平均をプロット ax, = df.plot1d(df.x, what='mean(E)', linewidth=5) # ↓はグラフの見た目調整 ax.axes.tick_params(axis='both', labelsize=20) ax.axes.xaxis.label.set_size(20) ax.axes.yaxis.label.set_size(20)
2次元においても同様に行えます。
# x, yでgroupbyしてEの平均をプロット ax = df.plot(df.x, df.y, what=vaex.stat.mean(df.E)) # ↓はグラフの見た目調整 ax.axes.tick_params(axis='both', labelsize=20) ax.axes.xaxis.label.set_size(20) ax.axes.yaxis.label.set_size(20)
ポイントは集約関数を伴うものに限られるということです。例えばScatterを書きたい場合は普通に evaluate
してからプロットするみたいです。
x = df.evaluate("x") y = df.evaluate("y") plt.scatter(x, y)
Join
JoinもPandasではcopyが発生しますが、copyなしで行うことができます。 次のようにPandasと同じようなAPIです。
a = np.array(['a', 'b', 'c']) x = np.arange(1,4) df1 = vaex.from_arrays(a=a, x=x) b = np.array(['a', 'b', 'd']) y = x**2 df2 = vaex.from_arrays(b=b, y=y) df1.join(df2, left_on='a', right_on='b')
注意点としては、Inner, Outer Joinが現状使えません。 ドキュメントの書き方だと今後はサポートされるかもですね。
JIT
なんとJust-In-Timeコンパイルもサポートしています。
使い方も簡単で evaluate()
する前に jit_numba()
を呼び出すだけです。
内部で使うJITコンパイラは別途インストールが必要なので適宜インストールしましょう。
pip install numba
exp = np.sqrt(df.x**2 + df.y**2 + df.z**2) df.evaluate(exp) df.evaluate(exp.jit_numba()) # JITコンパイルしたのち評価
機械学習
機械学習もアルゴリズムは限られていますが、サポートされています。
まず機械学習を行うためには vaex-ml
が必要なのでインストールしましょう。
pip install vaex-ml
サポートされているのは、KMeans/PCA/XGBoostですね。 あと前処理のOne-Hot-Encodingもサポートされています。
ここでは一番気になるXGBoostを使ってみます。
import vaex.ml.xgboost import vaex.ml.datasets # テストデータのIrisを使います。 df = vaex.ml.datasets.load_iris() # Train/Test 分割 df_train, df_test = df.ml.train_test_split() # 使う特徴量を設定します expressions = [ df.col.petal_width, df.col.petal_length, df.col.sepal_width, df.col.sepal_length ] features = [k.expression for k in expressions] # パラメータを設定します param = { 'max_depth': 3, # the maximum depth of each tree 'eta': 0.3, # the training step for each iteration 'silent': 1, # logging mode - quiet 'objective': 'multi:softmax', # error evaluation for multiclass training 'num_class': 3 # the number of classes that exist in this datset } num_round = 10 # 学習回数(おそらく) ※デフォルトが0なので注意 # モデルを作成します model = vaex.ml.xgboost.XGBModel(features=features, num_round=10, param=param) # 学習 model.fit(df_train, df_train.class_, copy=True) # 予測 df_predict = model.transform(df_test) df_predict
予測結果がこちらです。
ところどころAPIが違うので少々混乱しましたができました。 ドキュメントやAPIの感じからまだUnder Developmentな様子ですが、今後精微されてきたら実用できるかもですね。
まとめ
- Vaexの入門記事でした。
- Joinや機械学習までサポートされているのには驚きました。
- まだProductionで使う状態ではないと思いますが、小規模プロジェクトなどで使ってみたいですね。
- 自分もVaexについて知らないことばかりなので、皆さんと情報共有できたら嬉しいです!
- 今回使ったコードは↓のGitHubにあげています。