サイトアイコン アマチュア無線局JS2IIU

Panel応用編 第10回: データサイエンスパイプラインのためのPanel活用

こんにちは、JS2IIUです。Panel応用編は今回で一旦最終回です。面白い使い方を見つけたらまた記事にしていきたいと思います。それでは最終回、よろしくお願いします。

はじめに

データサイエンスは、データの収集、クリーニング、分析、モデル作成、可視化までの一連のプロセスを含む総合的なプロジェクトです。このプロセスを「データサイエンスパイプライン」と呼びます。本記事では、Panelを使ってデータサイエンスパイプラインの各ステップを統合し、データの処理から可視化、モデリングまでを一貫して行うダッシュボードを構築する方法を解説します。

データのインポートとクリーニング

まず、データサイエンスパイプラインの最初のステップであるデータのインポートとクリーニングを行います。Panelを使うことで、ユーザーがデータファイルをアップロードし、そのデータを自動的にクリーニングする機能を提供できます。

CSVファイルのアップロード

ユーザーがCSVファイルをアップロードし、その内容を表示・処理するためのインターフェースを作成します。CSVはどんなものでも大丈夫です。

import pandas as pd
import panel as pn
import io

pn.extension()

# ファイルアップロードウィジェット
file_input = pn.widgets.FileInput(name='Upload CSV File')

# アップロードしたデータを表示するためのパネル
data_pane = pn.pane.DataFrame(height=200)

# データの処理と表示を行う関数
def load_data(event):
    if file_input.value is not None:
        # io.BytesIO でバイナリデータを読み込む
        data = pd.read_csv(io.BytesIO(file_input.value))
        # データのクリーニング(欠損値の処理など)
        data_cleaned = data.dropna()  # 欠損値を削除
        data_pane.object = data_cleaned

# ボタンをクリックするとデータを読み込む
load_button = pn.widgets.Button(name='Load Data')
load_button.on_click(load_data)

# レイアウト
layout = pn.Column(
    "## Data Upload and Cleaning",
    file_input,
    load_button,
    data_pane
)

layout.servable()
pn.serve(layout)

欠損データがないCSVをアップロードした場合

https://js2iiu.com/wp-content/uploads/2024/09/pn_10_01.mov

欠損データがあるCSVをアップロードした場合

欠損値は2行目、3行目に存在していました。欠損値がない1行目だけが読み込まれました。

https://js2iiu.com/wp-content/uploads/2024/09/pn_10_02.mov

データのクリーニング

クリーニングのステップでは、欠損値の処理や異常値の削除、データの型変換など、データの前処理を行います。次のコードでは、欠損値の補完方法を選択できる機能を追加します。

# 欠損値処理の選択ウィジェット
missing_value_option = pn.widgets.Select(name='Missing Value Handling', options=['Drop Rows', 'Fill with Mean'])

def clean_data(event):
    if file_input.value is not None:
        data = pd.read_csv(file_input.file)
        if missing_value_option.value == 'Drop Rows':
            data_cleaned = data.dropna()
        elif missing_value_option.value == 'Fill with Mean':
            data_cleaned = data.fillna(data.mean())
        data_pane.object = data_cleaned

load_button.on_click(clean_data)

# レイアウトに追加
layout.insert(2, missing_value_option)
https://js2iiu.com/wp-content/uploads/2024/09/pn_10_03.mov

データの可視化

次のステップでは、クリーニング済みのデータを可視化します。Panelは、HoloViewsPlotlyと統合されており、インタラクティブなグラフやチャートを作成することができます。

HoloViewsを使ったデータ可視化

次に、HoloViewsを使って、データを簡単に可視化する例を見ていきます。データに基づいて散布図を作成し、特定のカラムを選択して表示します。

import holoviews as hv
import pandas as pd

# データの散布図を表示する関数
def visualize_data(data):
    scatter_plot = hv.Scatter(data, kdims='column_x', vdims='column_y')
    return pn.pane.HoloViews(scatter_plot)

# データに基づいて可視化を実行
if data_pane.object is not None:
    visualization_pane = visualize_data(data_pane.object)
else:
    visualization_pane = pn.pane.Markdown("No data to display.")

# レイアウトの更新
layout.append(visualization_pane)

全体を結合したプログラム

import pandas as pd
import panel as pn
import io
import matplotlib.pyplot as plt

pn.extension()

# ファイルアップロードウィジェット
file_input = pn.widgets.FileInput(name='Upload CSV File')

# アップロードしたデータを表示するためのパネル
data_pane = pn.pane.DataFrame(height=200)

# データの散布図を表示する関数 (matplotlibを使用)
def visualize_data(data):
    fig, ax = plt.subplots()
    ax.scatter(data['column_x'], data['column_y'])
    ax.set_xlabel('column_x')
    ax.set_ylabel('column_y')
    return fig

# 欠損値処理の選択ウィジェット
missing_value_option = pn.widgets.Select(name='Missing Value Handling', options=['Drop Rows', 'Fill with Mean'])

# データのクリーニングと可視化を行う関数
def clean_and_visualize_data(event):
    if file_input.value is not None:
        data = pd.read_csv(io.BytesIO(file_input.value))
        
        # 欠損値処理の選択に応じてデータを処理
        if missing_value_option.value == 'Drop Rows':
            data_cleaned = data.dropna()
        elif missing_value_option.value == 'Fill with Mean':
            data_cleaned = data.fillna(data.mean())
        
        data_pane.object = data_cleaned
        
        # 可視化処理
        if data_pane.object is not None:
            scatter_plot = visualize_data(data_cleaned)
            visualization_pane.object = pn.pane.Matplotlib(scatter_plot, tight=True)
        else:
            visualization_pane.object = pn.pane.Markdown("No data to display.")

# missing_value_optionの選択が変更されたときにclean_and_visualize_dataを呼び出す
missing_value_option.param.watch(clean_and_visualize_data, 'value')

# データの処理と表示を行う関数
def load_data(event):
    if file_input.value is not None:
        data = pd.read_csv(io.BytesIO(file_input.value))
        data_cleaned = data.dropna()  # 初回は欠損値を削除してクリーニング
        data_pane.object = data_cleaned
        
        # 初回の可視化
        scatter_plot = visualize_data(data_cleaned)
        visualization_pane.object = pn.pane.Matplotlib(scatter_plot, tight=True)

# ボタンをクリックするとデータを読み込む
load_button = pn.widgets.Button(name='Load Data')
load_button.on_click(load_data)

# レイアウト
visualization_pane = pn.panel(pn.pane.Markdown("No data to display."))

layout = pn.Column(
    file_input,
    missing_value_option,
    load_button,
    data_pane,
    visualization_pane
)

layout.show()

このプログラムは、ユーザーがアップロードした CSV ファイルを読み込み、欠損値を処理した後、HoloViews で散布図を描画し、Panel を使ってインタラクティブに表示する構成になっています。

プログラム全体の流れ

  1. ユーザーが CSV ファイルをアップロードする。
  2. アップロードされたデータから欠損値を処理し、クリーニングしたデータを用いて散布図を生成。
  3. 散布図をインタラクティブに表示するため、Panel を使ったユーザーインターフェースが提供される。

1. 必要なライブラリのインポート

import holoviews as hv
import pandas as pd
import panel as pn
import io

2. 拡張機能の有効化

pn.extension()
hv.extension('bokeh')

3. ファイルアップロードウィジェット

file_input = pn.widgets.FileInput(name='Upload CSV File')

4. データ表示パネル

data_pane = pn.pane.DataFrame(height=200)

5. 散布図を作成する関数

def visualize_data(data):
    scatter_plot = hv.Scatter(data, kdims='column_x', vdims='column_y')
    return scatter_plot

6. 欠損値処理の選択ウィジェット

missing_value_option = pn.widgets.Select(name='Missing Value Handling', options=['Drop Rows', 'Fill with Mean'])

7. データのクリーニングと可視化を行う関数

def clean_and_visualize_data(event):
    if file_input.value is not None:
        data = pd.read_csv(io.BytesIO(file_input.value))

        # 欠損値処理の選択に基づいてデータをクリーニング
        if missing_value_option.value == 'Drop Rows':
            data_cleaned = data.dropna()
        elif missing_value_option.value == 'Fill with Mean':
            data_cleaned = data.fillna(data.mean())

        data_pane.object = data_cleaned  # クリーニング済みデータを表示

        if data_pane.object is not None:
            scatter_plot = visualize_data(data_cleaned)
            visualization_pane.object = pn.panel(hv.render(scatter_plot, backend='bokeh'))
        else:
            visualization_pane.object = pn.pane.Markdown("No data to display.")

8. 欠損値処理の変更に応じた処理のトリガー

missing_value_option.param.watch(clean_and_visualize_data, 'value')

9. データ読み込みと初回の可視化を行う関数

def load_data(event):
    if file_input.value is not None:
        data = pd.read_csv(io.BytesIO(file_input.value))
        data_cleaned = data.dropna()  # 初回は欠損値を削除
        data_pane.object = data_cleaned

        scatter_plot = visualize_data(data_cleaned)
        visualization_pane.object = pn.panel(hv.render(scatter_plot, backend='bokeh'))

10. ボタンの作成とクリックイベントの設定

load_button = pn.widgets.Button(name='Load Data')
load_button.on_click(load_data)

11. レイアウトの設定とアプリケーションの表示

visualization_pane = pn.panel(pn.pane.Markdown("No data to display."))

layout = pn.Column(
    file_input,
    missing_value_option,
    load_button,
    data_pane,
    visualization_pane
)

layout.servable()
pn.serve(layout)

まとめ

このプログラムは、ユーザーがアップロードした CSV ファイルを読み込み、欠損値の処理オプションを選択してデータをクリーニングした後、HoloViews を使用してインタラクティブな散布図を描画します。また、Panel を使ってユーザーインターフェースを提供し、インタラクティブなデータ処理と可視化が可能なアプリケーションを構築しています。

モデルの訓練と予測

次に、クリーニング済みデータを使って機械学習モデルを訓練し、予測を行います。この例では、Scikit-learnを使ったシンプルな線形回帰モデルを訓練します。

線形回帰モデルの訓練

from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split

# データが準備できた場合の処理
def train_model(event):
    if data_pane.object is not None:
        data = data_pane.object
        X = data[['column_x']].values
        y = data[['column_y']].values
        X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

        model = LinearRegression()
        model.fit(X_train, y_train)

        prediction = model.predict(X_test)
        return prediction

モデルの予測結果を表示

# 予測結果を表示するためのパネル
prediction_pane = pn.pane.Markdown("## Model Predictions: ")

def display_predictions(event):
    predictions = train_model(event)
    prediction_pane.object = f"## Predictions: {predictions}"

# ボタンクリックで予測を実行
predict_button = pn.widgets.Button(name='Predict')
predict_button.on_click(display_predictions)

# レイアウトに予測結果を追加
layout.append(predict_button)
layout.append(prediction_pane)

データサイエンスパイプラインの統合

最後に、これまでのデータのインポート、クリーニング、可視化、モデリングをすべて統合し、Panelダッシュボードとして一貫したワークフローを提供します。

layout = pn.Column(
    "## Data Science Pipeline",
    file_input,
    load_button,
    missing_value_option,
    data_pane,
    predict_button,
    prediction_pane,
    visualization_pane
)

layout.servable()
pn.serve()

このレイアウトは、データサイエンスパイプライン全体をカバーするUIを作成し、Panelの強力な機能を活用して、インタラクティブで直感的なデータサイエンスダッシュボードを実現します。

まとめ

今回の記事では、Panelを活用してデータサイエンスパイプラインを一貫して構築する方法を紹介しました。具体的には、データのインポート、クリーニング、可視化、そして機械学習モデルの訓練と予測を行うフローを作成しました。Panelの強力なウィジェット機能や、Scikit-learn、HoloViewsなどのツールを統合することで、インタラクティブなデータサイエンスダッシュボードが簡単に作成できることを確認しました。

この手法を使えば、データ処理や可視化、モデリングを統合した一貫性のあるワークフローを構築でき、データサイエンティストやエンジニアにとって効率的なデータ分析環境を提供できます。これでPanel応用編シリーズは完結ですが、今後のデータサイエンスプロジェクトにぜひ活用してください。

モバイルバージョンを終了