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

Python
この記事は約19分で読めます。

こんにちは、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)
  • FileInput ウィジェットを使って、ユーザーがCSVファイルをアップロードできるようにします。
  • pd.read_csv() でアップロードされたCSVファイルをPandasのデータフレームに読み込み、dropna() を使って欠損値を削除するなどのクリーニング処理を実施します。
  • アップロードされたデータは、DataFrameパネルに表示され、ユーザーがデータを確認できます。

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

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

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

データのクリーニング

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

# 欠損値処理の選択ウィジェット
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)
  • Select ウィジェットを使って、欠損値処理の方法(行の削除または平均値での補完)を選択できるようにします。
  • ユーザーが選択したオプションに基づいて、欠損値の処理方法を変更し、データをクリーニングします。

データの可視化

次のステップでは、クリーニング済みのデータを可視化します。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)
  • HoloViewsScatterプロットを使って、2つのカラム間の関係を可視化します。kdims でx軸、vdims でy軸のカラムを指定します。
  • データが存在する場合は散布図を表示し、存在しない場合はメッセージを表示します。
  • Panelモジュールのバグがあり、図を表示できない場合があります。エラーが出てしまう場合は、コメント欄にメッセージお願いします。

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

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
  • holoviews: インタラクティブなデータ可視化を行うためのライブラリ。ここでは散布図を作成するために使用します。
  • pandas: CSV ファイルを読み込み、データの処理やクリーニングを行うために使用します。
  • panel: ウェブアプリケーションのインターフェースを構築するためのライブラリ。ファイルアップロードや可視化のための UI を提供します。
  • io: ファイルの読み書きを扱う Python の標準モジュールで、バイナリデータを処理するために使用します。

2. 拡張機能の有効化

pn.extension()
hv.extension('bokeh')
  • pn.extension() は、Panel のウィジェットやインターフェース機能を利用可能にします。
  • hv.extension('bokeh') は、HoloViews でグラフを描画する際に使用する描画バックエンドとして Bokeh を選択しています。

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

file_input = pn.widgets.FileInput(name='Upload CSV File')
  • FileInput ウィジェットは、ユーザーがローカルから CSV ファイルをアップロードできる UI コンポーネントです。Panel では、ファイルがアップロードされるとそのファイルデータがバイナリ形式で保持されます。

4. データ表示パネル

data_pane = pn.pane.DataFrame(height=200)
  • pn.pane.DataFrame は、アップロードされた CSV ファイルのデータを表示するためのパネルです。このパネルには、pandas.DataFrame オブジェクトを表示でき、指定した高さ(ここでは 200 ピクセル)でデータが表示されます。

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

def visualize_data(data):
    scatter_plot = hv.Scatter(data, kdims='column_x', vdims='column_y')
    return scatter_plot
  • visualize_data 関数は、CSV ファイルから読み込まれたデータをもとに HoloViewsScatter オブジェクトを作成します。
  • kdims(キー次元)と vdims(値次元)で、散布図の x 軸と y 軸に対応するデータ列を指定しています。

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

missing_value_option = pn.widgets.Select(name='Missing Value Handling', options=['Drop Rows', 'Fill with Mean'])
  • Select ウィジェットを使用して、欠損値処理の方法をユーザーが選択できるようにしています。
  • 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.")
  • file_input.valueNone でない場合、pandas を使って CSV ファイルを読み込みます。
  • missing_value_option の選択に基づいて欠損値を処理します。Drop Rows なら欠損値を含む行を削除、Fill with Mean なら欠損値を列の平均値で埋めます。
  • 処理したデータを data_pane に表示し、クリーニング後のデータを用いて visualize_data 関数で散布図を作成し、visualization_pane に表示します。

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

missing_value_option.param.watch(clean_and_visualize_data, 'value')
  • missing_value_option の選択が変更されたときに clean_and_visualize_data 関数が呼び出されるように、watch メソッドでイベントリスナーを設定します。

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'))
  • この関数は、file_input からデータを読み込み、欠損値を削除してクリーニングします。その後、クリーニングされたデータを用いて初回の散布図を作成し、表示します。

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

load_button = pn.widgets.Button(name='Load Data')
load_button.on_click(load_data)
  • 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)
  • 散布図を表示するパネルの初期状態は “No data to display.” というテキストを表示しています。
  • pn.Column で、UI コンポーネントを縦に並べてレイアウトを作成します。このレイアウトには、ファイルアップロードウィジェット、欠損値処理選択ウィジェット、データ読み込みボタン、データ表示パネル、散布図表示パネルが含まれています。
  • layout.servable() を呼び出して、このレイアウトを Panel アプリケーションとして提供します。pn.serve() でアプリケーションを実行し、ウェブブラウザ上に表示します。

まとめ

このプログラムは、ユーザーがアップロードした 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
  • LinearRegression モデルを使って、クリーニングされたデータをもとにモデルを訓練し、データの予測を行います。
  • train_test_split() で訓練データとテストデータに分割し、モデルの訓練後にテストデータで予測を実施します。

モデルの予測結果を表示

# 予測結果を表示するためのパネル
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)
  • Markdown パネルに予測結果を表示し、ユーザーがクリックすることでモデルの予測結果がリアルタイムで表示されます。
  • predict_button をクリックすると、display_predictions() 関数が呼び出され、モデルの予測結果を表示します。

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

最後に、これまでのデータのインポート、クリーニング、可視化、モデリングをすべて統合し、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応用編シリーズは完結ですが、今後のデータサイエンスプロジェクトにぜひ活用してください。

コメント

タイトルとURLをコピーしました