新しいデータ処理ライブラリの学習はもう不要！ Python 初学者のための Ibis 100 本ノック

![ibis.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692165/91c03770-b440-648c-c637-61aff44eee36.png)

**Information**

**2024/7/24：**
- **Ibis-Polars vs Native Polars**
Ibis-Polars と Native Polars の処理速度の比較記事を書かれている方がおりました。
Ibis 経由で Polars を使用しても Polars と処理速度に大きな差がないことを示していました。
[ibis-frameworkでPolarsとSQLをつかってみた](https://qiita.com/shotakawaguchi/items/016a5be2c8efd24e14a2)

**2024/1/14：**
- **Kaggle notebook for Ibis**
Kaggle で Ibis を使用するための Sample Notebook を用意しました。Kaggle でもぜひ Ibis をご活用下さい。
[🦩 [Ibis] Kaggle-Titanic-Tutorial](https://www.kaggle.com/code/shouheikuniyoshi/ibis-kaggle-titanic-tutorial)
　　
- **Ibis 100 本ノック補足記事**
Ibis 100 本ノックについて、よりスマートな書き方等について @hkzm さんが補足記事を書いてくれました（この記事を参考にコンテンツのほうもブラッシュアップしたいと思います）。
[Ibis 100 本ノックの記事を受けて](https://qiita.com/hkzm/items/0e0972e6f0a63423771e)

# はじめに
どうもこんにちは、kunishou です。
　
この度 Ibis という、Python の統合データ処理ライブラリを効率的に学ぶためのコンテンツとして  **「 Python 初学者のための Ibis 100 本ノック」**  を作成したので公開します。こちらは過去に公開した[「 Python 初学者のための pandas 100 本ノック」](https://qiita.com/kunishou/items/bd5fad9a334f4f5be51c)、[「 Python 初学者のための Polars 100 本ノック」](https://qiita.com/kunishou/items/1386d14a136f585e504e)の問題内容を Ibis のメソッドに合わせて修正、再編したものになります。本コンテンツに取り組むことで Ibis を用いたひと通りのデータ操作、データ処理を実施できるようになります。また、本コンテンツは **Google Colab 上で実施できるため、PC とインターネット環境があれば、Python 環境を構築することなくすぐに Ibis の学習を始めることができます。**

**以下に、コンテンツのイメージ動画を載せておきます**
※動画は過去に作成した pandas 100 本ノックのものであり、今回ランダムノック版は作成していません
<Br>
<iframe width="560" height="400" src="https://www.youtube.com/embed/apYJZbiM_D4" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

# Why Ibis ？
いきなり Ibis 100 本ノックの紹介から入りましたが本記事では、なぜ Ibis が必要なのか、データ処理ライブラリとしてどういう点が優れているのかについて、データ処理の現状や課題に触れながら説明し、記事後半に 100 本ノックの内容について説明したいと思います。

### 本記事の構成
- 記事前半
データ処理の現状と課題、Ibis の特徴について
- 記事後半
Ibis 100 本ノックについて

# データ処理の現状[^1]
データ分析において普段、皆さんはどのライブラリを用いてデータ処理を行っていますでしょうか？おそらく pandas を使っているという人が圧倒的に多いと思います。実際、データ処理をする上で pandas は非常に優秀で、数年前までは pandas が Python エコシステム内のあらゆるデータを扱うための最適なライブラリでした。しかし、近年、データ分析やデータエンジニアリング分野の進化、多様化が急速に進み pandas が常に最適なライブラリではなくなってきました。

- **データ分析分野**
数年前までは pandas だけであらゆるデータ分析を行うことができました。しかし、データ分析に求められるものが高度化したり、扱うデータの大規模化が進む中、pandas では満足のいくデータ処理ができないシーンが多くなってきました。そのため近年では Dask や Polars と言った、より高速にデータ処理を行なえるライブラリも使われるようになってきました。では、 Dask や Polars を使えるようになれば問題ないのでしょうか？ **今後もデータ分析への要求の高度化、データの大規模化は進み、数年後にはまた新しいデータ処理ライブラリが登場すると予想されます。そのため、データ分析従事者は、今後も新たなライブラリを使うための継続的な学習が必要になると考えられます。**
<br>

- **データエンジニアリング分野**
自社のデータ基盤に応じてデータ処理ライブラリを学習する必要があります。データ基盤の技術も日々進化、多様化しており、自社のデータ基盤が Hadoop であれば PySpark を学ぶ必要がありますが、そこから基盤が Google Cloud に移行、併用するようになれば、 BigQuery も学ばなくてはいけなく、 **開発で使うデータ基盤に合わせてデータ処理の手段を学習し続けなくてはいけません。またデータ基盤を移行する場合はこれまで使用していたデータ処理パイプラインのコードを書き換える必要もあります。**

## データ処理に今後求められること[^1]
- **データ処理フレームワークのモジュール化へのシフト**
データ分析やデータエンジニアリング分野の進化、多様化を踏まえ、従来のように pandas のような特定のライブラリに依存するのではなく、様々なユースケースに合わせて最適なフレームワーク（ライブラリや手段）をモジュールとして柔軟に選択でき、低コストで開発を継続できることが重要になります（これは pandas コア開発者の Marc Garcia 氏も提唱しています）。


## データ処理の課題まとめ
1. データ処理ライブラリやデータ基盤が進化、多様化するごとに新しいデータ処理ライブラリを学習する必要があり、 **継続的な学習コストが発生**
2. データ処理ライブラリの変更やデータ基盤の移行の都度、 **データ処理パイプラインのコード書き換え作業コストが発生**

ここまでの説明で、データ処理の現状や課題が理解できたかと思います。以降では、これらの課題を解決するのに Ibis が非常に有効であることを説明していきたいと思います。

# 統合データ処理ライブラリとしての Ibis
Ibis は統合的にデータ処理を実行可能なインターフェースを提供するライブラリで、 **現在サポートしている18を超えるデータ処理ライブラリを同一の記法で使用することができます。**

※ ちなみに Ibis は英語で「トキ」のことを指します。

- 公式 Reference

https://ibis-project.org/

- Github

https://github.com/ibis-project

### 2024年1月現在サポートしているエンジン
BigQuery , ClickHouse , Dask , DataFusion , Druid ,
DuckDB（ MotherDuck への接続もサポート） , Exasol ,
Flink , Impala , MSSQL , MySQL , Oracle , pandas ( CuDF ) , Polars ,
PostresSQL , PySpark , Snowflake , SQLite , Trino

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692165/4986db62-eaa3-ea67-a4bf-7accb9092145.png)
画像引用：https://voltrondata.com/resources/ibis-cudf-pandas

Ibis は必要な時にいつでもバックエンドの処理エンジンを切り替えることができるライブラリであり、様々なユースケースに柔軟に、低コストで対応することができます。以下のように異なるフレームワークをすべて同じ記法でデータ操作することができます。

- バックエンドの処理エンジンとして pandas を使用する場合
 ```python:backend pandas
ibis.set_backend("pandas") # pandas をバックエンドに指定

t = (
    ibis.read_csv("titanic.csv")
    .select("name", "sex", "age", "fare")
    .filter(t["sex"] == "female")
    .mutate(
        # age と fare の偏差値集計
        s.across(["age", "fare"] , {"zscore": lambda x: ((x - x.mean()) / x.std()) * 10 + 50}))
    .order_by(ibis.desc("age")) # age 列で降順ソート
    )

t.execute() # クエリの実行
    
 ```

- バックエンドの処理エンジンとして Polars を使用する場合

 ```python:backend polars
ibis.set_backend("polars") # polars をバックエンドに指定

t = (
    ibis.read_csv("titanic.csv")
    .select("name", "sex", "age", "fare")
    .filter(t["sex"] == "female")
    .mutate(
        # age と fare の偏差値集計
        s.across(["age", "fare"] , {"zscore": lambda x: ((x - x.mean()) / x.std()) * 10 + 50}))
    .order_by(ibis.desc("age")) # age 列で降順ソート
    )

t.execute() # クエリの実行
    
 ```

 上記のコード例のように **冒頭1行目を修正するだけでバックエンドの処理エンジンを pandas から polars に切り替えることができました。**

数年後に仮に、`neo-pandas` という新規ライブラリが登場し、それを Ibis がサポートした場合、以下のようにバックエンドを指定すればすぐに利用することができます（既存コードの書き換えは不要です）。

 ```python:backend neo-pandas
 
ibis.set_backend("neo-pandas") # neo-pandas をバックエンドに指定
    
 ```

このように Ibis を利用することで、データ分析、データエンジニアリング分野の進化、多様化に伴い発生する **新しいライブラリの学習コストやコード書き換えの作業コストを限りなく少なくすることができます。**

# Ibis の概要、特徴
この章では Ibis の概要、特徴について紹介していきます。

- 様々なデータ処理ライブラリを同一の記法で書け、現在18を超えるライブラリをサポートしている。 **2023年12月には CuDF にも対応し、CuDF 拡張を読み込むためのコード1行を追加するだけでバックエンドを CuDF にしてデータ操作をすることができる。** バックエンドを CPU環境では Polars 、GPU環境では CuDF という具合に環境に応じて同じパイプラインを使い分けることができそうです。Ibis での CuDF の使用方法に関する記事は以下を参照して下さい。

https://voltrondata.com/resources/ibis-cudf-pandas

- Ibis は、 **統一された API インターフェースの提供と、入力されたAPIを各エンジンで処理するための形式に変換し、処理エンジンに渡す役割を担っており、** Ibis 自体がデータ処理をしているわけではない（人間の言語で例えると、Ibisは Ibis語を各データフレーム言語に翻訳してくれる通訳のようなイメージ。  **データ処理ライブラリと言うよりインターフェースと言ったほうが良さそうです**）。
- 現在、 **スポンサーも付いており、開発は鋭意進行中** で、サポートするフレームワークも増えている（2023年には SnowFlake , Trino , Polars, CuDF 等に対応）。
- **2015年から開発されており破壊的な変更が少ない。** 例えば、現在、CPU環境での処理速度が速いと言われている Polars は下記記事の通り急速に開発が進められている関係で破壊的な変更が多く、仕様変更を常にキャッチアップする必要があるが Ibis ではその心配は少ない。

https://qiita.com/hkzm/items/9da3ecf4024e3798403b

- **pandasのコア開発者である Marc Garcia 氏が開発に携わっている**（前述でモジュール化を提唱していた人です）。
- **Google の DVT（データ検証ツール）のバックボーンに採用されている。[^2]** 複数の異なるデータベースに同時接続できるIbisを使うことでクロスバックエンドでのデータ比較検証が可能になり、顧客の環境から Google Cloud への移行時の検証に活用されている。

>The Data Validation Tool is an open sourced Python CLI tool **based on the Ibis framework** that compares heterogeneous data source tables with multi-leveled validation functions.

https://github.com/GoogleCloudPlatform/professional-services-data-validator?utm_source=pocket_saves

# Ibis の特徴まとめ
- Ibisは、単一のデータ処理フレームワークに依存せず、あらゆるユースケースに対して手段を柔軟に選択できることを志向した統合データ処理ライブラリである。
- Ibis ではバックエンドを切り替えるだけで18を超えるデータ処理フレームワークを少ないコード修正で利用することができ、新しいライブラリの学習コストや、データ処理パイプラインのコード書き換え作業コストを限りなく少なくすることができる。
- スポンサーが付き現在も開発が鋭意進行していること、pandas のコア開発者が開発に携わっていること、Google の DVT（データ検証ツール）に採用されていることから、 **ライブラリとしての将来性は明るい。**

# Ibis の利用シーン
この章では、実際どういったシーンで Ibis が有効であるかの想定事例を紹介します。なお、あくまでも一例で、これ以外にも活用シーンはあると思います。

### ローカル環境とステージング環境以降でデータ処理手段を変えたい[^3]
例えば、Hadoop から PySpark でデータ抽出が必要なプロダクト開発があった場合、ローカル環境での開発から PySpark を使用すると困難になることがあります。これは、PySpark が大規模なデータセットと分散コンピューティング環境に最適化されているためです。このようなケースでは、まずローカル環境（単一ノード）での開発は、例えば DuckDB で行い、ステージング環境（複数ノード）以降でパイプラインを PySpark に書き換えることが多いかと思います。このようなケースで Ibis を使えれば、ステージング環境以降でのコード書き換えは発生せず、開発フェーズに応じてバックエンドを DuckDB から PySpark に切り替えるだけで済ませることができます。

### 複数のデータ基盤を横断するプロダクト
企業によっては、データのセキュリティレベルによってデータを管理する基盤を使い分けているところも多いかと思います。例えば、 データ X は オンプレ環境の Hadoop から PySpark で抽出し、データ Y については Google Cloud から BigQuery で抽出するようなケースがあった場合、担当者は両方のデータ処理フレームワークを学習する必要があります。もしくは、PySpark が使える A さんと BigQuery が使える B さんの二人で開発を担当するケースもありそうです。後者の場合は、開発の担当が属人化する可能性もあります。このようなケースで Ibis を使えれば、余計な学習コストを抑えられ、また、Ibis を使える開発メンバーであれば誰でもパイプラインを開発・保守することができ、属人化も防止できます。

### Ibis 移行において SQL コードを流用したい
データ処理手段を Ibis に移行する際のコード書き換えを最小限に抑えることも可能です。Ibis では実行コードに SQL を含めることができるため、元のデータ基盤で SQL でデータ抽出していた場合、その SQL をそのまま流用することが可能です。以下は、DuckDB においてデータ処理手段を SQL から Ibis に移行する際に SQL を流用するコードの例です。 .sql() に DuckDB の SQL を渡せば元の SQL を流用してデータ処理を行うことができます。この方法により、Ibis を導入する場合の SQL を Ibis メソッドに書き換える作業は不要になります。

```python
ibis.set_backend("duckdb") # バックエンドに DuckDB を指定

t = ibis.read_csv("titanic.csv", table_name="titanic")

(
t.sql("""
  select
    *
  from titanic
  where sex = 'male'
  and name like '%Allison%'
  """)
)

```

### データ基盤移行において SQL コードを流用したい
データ基盤の移行に伴うコード書き換えを最小限に抑えたい場合、これも Ibis で実現できる場合があります。例えば、元々、 MySQL を利用していて DuckDB に移行することになった場合、MySQL で使用していた SQL をそのまま流用することができます。 Ibis では実行コードに SQL を含めることができ、かつ SQL 方言を吸収させる機能もあります。以下のように .sql() の dialect 引数で SQL の種類を指定することで バックエンドは DuckDB だけども MySQL の SQL でデータ処理を行うことが可能です。この方法により、データ基盤移行に伴う SQL の DuckDB 様式への書き換え作業や、SQL を Ibis メソッドに書き換える作業は不要になります。

```python:backend DuckDB における MySQL SQL の実行
ibis.set_backend("duckdb") # バックエンドに DuckDB を指定

t = ibis.read_csv("titanic.csv", table_name="titanic")

# MySQL の SQL
sql = """
      select
        `name`,
        `sex`,
        `age`,
        `fare`
      from `titanic`
      where `age` >= 30
      """

t.sql(sql, dialect="mysql") # dialect で SQL の種類を指定

```

# その他の機能
Ibis には上記で説明した機能以外にも、機械学習へのデータのパイプをシームレスに行うための IbisML や、dbt モデルを Ibis で作成するための dbt-ibis など、便利なツールが多数用意されています。私も詳細を把握できていないため本記事では説明しませんが、興味のある方はぜひ調べてみて下さい。

```python:Example IbisML
import ibis
import ibisml as ml

# Load some training and testing data
train = ibis.read_csv("training.csv")
test = ibis.read_csv("testing.csv")

# A recipe for a feature engineering pipeline that:
# - imputes missing values in numeric columns with their mean
# - applies standard scaling to all numeric columns
# - one-hot-encodes all nominal columns
recipe = ml.Recipe(
    ml.ImputeMean(ml.numeric()),
    ml.ScaleStandard(ml.numeric()),
    ml.OneHotEncode(ml.nominal()),
)

# Fit the recipe against the training data
transform = recipe.fit(train, outcomes=["outcome_col"])

# Transform the training data and train a scikit-learn model
from sklearn.svm import LinearSVC
model = LinearSVC()

df_train = transform(train).to_pandas()
X = df_train[transform.features]
y = df_train[transform.outcomes]
model.fit(X, y)

# Transform the testing data and use the model to predict results
df_test = transform(test).to_pandas()
X = df_test[transform.features]
y = df_test[transform.outcomes]
y_pred = model.predict(X)
```

https://github.com/ibis-project/ibisml

https://binste.github.io/dbt-ibis/intro.html

以上、ここまでで Ibis の概要、メリット、どういうシーンで活用できそうかを紹介しました。 **無駄な開発コストの抑制は持続的な開発の実現にも繋がる** ため、もし、メリットがありそうだなと感じていただけたのであれば、是非 Ibis 100 本ノックの方にもトライしてみて下さい！

# Ibis 100 本ノックについて
### Ibis_100_knocks
統合データ処理ライブラリ Ibis を効率的に学習するためのコンテンツです。おそらく Ibis の使用方法を網羅的にまとめた国内初の Ibis 学習コンテンツだと思います（ちなみに海外でもあまり学習コンテンツがなさそうだったので今回は英語版も作成しました）。

https://github.com/kunishou/Ibis_100_knocks

### コンテンツ概要

- Notebook 上のセルに記載された Ibis メソッドに関する設問 100 問を解いていきます（タイタニック号の乗客データ等の実在するデータに対して Ibis メソッドで処理を実行していきます）。
- Githubのレポジトリには Google Colab 版が用意してあり、Python 環境の構築不要で、すぐにコンテンツを利用することが可能です。
- セクションは、基礎 (1-16)、抽出 (17-33)、加工 (34-61)、マージと連結 (62-67)、統計 (68-80)、ラベリング (81-82)、SQL (83-85)、グラフ (87-88)、その他 (89)、タイタニック号乗客の生存予測(90-100)の 10 個に分かれています。

例えば、Notebook のセルに以下のような問題が記載されています。ここに解答コードを記入し、実行して処理結果を確認します。
```
# 【8】
# t を fare の列で昇順に並び替えて表示しましょう

# print(ans[8]) # 解答表示
t = initialize1() # 初期化
# -----------------------------------------



```
解答を確認したい場合は、「# print(ans[8])」の「#」を削除して実行すると以下のように解答のコードや Tips を表示することができます。また、すべての解答に **pandas で書く場合の記法も載せています。**

```
[answer8]

t.order_by("fare") # 昇順ソート
# t.order_by(ibis.desc("fare")) # 降順ソート

----------------------------------------------

[Tips]
・.order_by() メソッドを使用することで、特定の列でデータをソートできる。
　デフォルトでは昇順になっている。
・降順でソートしたい場合は t.order_by(t["fare"].desc()) のように書く。
・t.order_by(ibis.desc("fare")) と書いても降順ソートができる。
・複数列でソートすることも可能

ex1) fare列で昇順ソートした後にage列で昇順ソートしたい場合
※ リスト内でage列を先に書く点に注意

t.order_by(["age", "fare"])

ex2) fare列で降順ソートした後にage列で降順ソートしたい場合
※ リスト内でage列を先に書く点に注意

t.order_by([ibis.desc("age"), ibis.desc("fare")])

ex3) fare列で降順ソートした後にage列で昇順ソートしたい場合
※ リスト内でage列を先に書く点に注意

t.order_by([ibis.asc("age"), ibis.desc("fare")])

----------------------------------------------

[参考] pandas記法

df.sort_values('fare')
```
# 利用方法
Google Colab 上で実施できるため Python 環境を構築することなく利用可能です。なお、問題を解く前に「全解答表示版」を見て一度メソッドを把握することを推奨します。

## Google Colab
[GitHub](https://github.com/kunishou/Ibis_100_knocks)のページに移動し、以下のリンクから Colab のページに移動できます。

- **Ibis 100 本ノック**

https://colab.research.google.com/drive/10Cqmh79CXQi6VASd-jcSz18wXVo7SzJW?usp=sharing

- **全解答表示板** （初めはこちらの閲覧を推奨）

https://colab.research.google.com/drive/1eHo1pP5ll4YqYGP5P-Eg7nwEzy9voSJs?usp=sharing

* ipynbファイルを開いた後に、先頭のセルを実行すると解答ファイル、問題で使用するデータセットのダウンロードおよび読み込みがされます。使用するデータセットは、タイタニック号の乗客データ等になっています。
* 各設問のセル内に設問に対するコードを入力していきます。
* 答えが分からない場合は、設問セル内の「#print(ans[])」という記述から「#」を消して実行することで、解答例が表示されます。  
* [全解答表示板](https://drive.google.com/file/d/1IL8VDAkqrSG7ixWrnpGuF2_k7-e1NfFi/view?usp=sharing)では、すべての解答と出力結果を最初から表示しています。解答や出力結果をまとめて確認したいときにご活用下さい。**Ibis を一度も触ったことのない方はまずこちらの全解答表示版のほうを流し見してひと通りメソッドを確認してみると良いと思います。**

# ディレクトリ構成
Ibis_100_knocks
　├ input_ja/ …　100 問分の解答ファイル、問題で使用するデータセットが格納（日本語版）
  ├ input_en/ …　100 問分の解答ファイル、問題で使用するデータセットが格納（英語版）
　└ output/ …　問題でファイル出力する際にここに格納

# その他
- 100 本ノック学習後に、Ibis をローカル環境で使用したいときは `pip install ibis-framework` で自身の環境にインストールする。なお、 `pip install ibis` とするとまったく違うライブラリがインストールされるため注意すること。
- Ibis インストール時はバックエンドで使用するライブラリもオプションで指定する。DuckDB がデフォルトのバックエンドなので 基本は `pip install ibis-framework[duckdb]` となる。

```python:pip install
pip install ibis-framework[duckdb] # 通常のインストール
pip install ibis-framework[duckdb,pandas] # pandas をバックエンドで使用したい場合
```
- Ibis でサポートしている18超の処理エンジンにおいて、エンジンごとにサポートしていないメソッドが存在する場合があります。例えば、DuckDB バックエンドではコード中で SQL を実行する .sql() メソッドが使用できますが、 pandas バックエンドでは SQL には対応していないので .sql() メソッドは使用できません。処理エンジンとサポートメソッドの対応について以下の表を参考にして下さい。

https://ibis-project.streamlit.app

# Ibis 100本ノック利用にあたっての留意点
- Python 初学者が利用することを前提に作成しているため、内容は比較的簡易なものになっています。
- pandas 100 本ノックがもともと「 Python3 エンジニア 認定データ分析試験」の出題内容に沿って作成していたため問題に偏りがありましたが、Ibis 版は内容が網羅的になるよう再編しています。
- **Ibis には、ひとつの処理をする場合でもいろいろな書き方があるため、ここに記載してる解答が唯一の解答ではありません** （ 例えば、select を用いてデータ選択する問題は、t["列名"] のように書けくこともできます）。
- 公式リファレンスの内容を完全に把握できているわけではないため、ベストプラクティスな書き方を確認でき次第、解答も随時更新していきます。

# 使用範囲／注意事項
* 使用範囲
個人・法人を問わず誰でも使用可能
(有志の勉強会や社内の研修で使う際、ご一報いただけると作者のモチベーションが上がります)

* 注意事項
コンテンツの再配布・改編は不可

# おわりに
今回、Ibis 100 本ノックというコンテンツについて紹介させていただきました。
本コンテンツに関して質問・要望があればご連絡下さい。

[^1]:[The Standard Dataframe Language for Data Analysis and Data Engineering](https://voltrondata.com/resources/ibis-standard-dataframe-language-data-analysis-engineering)
[^2]:[How Google Uses Ibis for its Data Validation Tool (DVT)](https://voltrondata.com/resources/how-google-uses-ibis-for-its-data-validation-tool-dvt)
[^3]:[Scaling Out to Apache Spark with Ibis](https://voltrondata.com/resources/scaling-out-to-apache-spark-with-ibis)