チュートリアル パート 2: Microsoft Fabric ノートブックを使用してデータを探索して視覚化する

このチュートリアルでは、探索的データ分析 (EDA) を実施し、データ視覚化手法を使ってデータの主な特徴を要約しながら、データを確認および調査する方法について説明します。

seaborn (データフレームと配列でビジュアルを構築するための高度なインターフェイスを提供する Python データ視覚化ライブラリ) を使います。 seaborn の詳細については、「Seaborn: 統計データの視覚化」を参照してください。

また、Data Wrangler (探索的データ分析とクリーニングを実行するためのイマーシブ エクスペリエンスを提供するノートブック ベースのツール) も使います。

このチュートリアルの主な手順は次のとおりです。

  1. レイクハウス内の差分テーブルから格納データを読み取ります。
  2. Spark データフレームを、Python 視覚化ライブラリでサポートされている Pandas データフレームに変換します。
  3. Data Wrangler を使って、初期データのクリーニングと変換を実行します。
  4. seaborn を使って探索的データ分析を実行します。

前提条件

これは、5 部構成のチュートリアル シリーズのパート 2 です。 このチュートリアルを完了するには、最初に次の手順を完了します。

ノートブックで作業を進める

2-explore-cleanse-data.ipynb は、このチュートリアルに付属するノートブックです。

このチュートリアルに付随するノートブックを開くには、「データ サイエンス用にシステムを準備する」チュートリアル の手順に従い、ノートブックをお使いのワークスペースにインポートします。

このページからコードをコピーして貼り付ける場合は、[新しいノートブックを作成する] ことができます。

コードの実行を開始する前に、必ずレイクハウスをノートブックにアタッチしてください。

重要

パート 1 で使ったものと同じレイクハウスをアタッチします。

レイクハウスから生データを読み取る

レイクハウスの [ファイル] セクションから生データを読み取ります。 前のノートブックでこのデータをアップロードしました。 このコードを実行する前に、パート 1 で使ったものと同じレイクハウスをこのノートブックにアタッチしていることを確認します。

df = (
    spark.read.option("header", True)
    .option("inferSchema", True)
    .csv("Files/churn/raw/churn.csv")
    .cache()
)

データセットから pandas データフレームを作成する

処理と視覚化を容易にするために、spark データフレームを pandas データフレームに変換します。

df = df.toPandas()

生データを表示する

display を使用して生データを探索し、基本的な統計の実行およびグラフ ビューの表示を行います。 データ分析と視覚化に必要なライブラリ (NumpyPnadasSeabornMatplotlib など) をインポートする必要があることに注意してください。

import seaborn as sns
sns.set_theme(style="whitegrid", palette="tab10", rc = {'figure.figsize':(9,6)})
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
from matplotlib import rc, rcParams
import numpy as np
import pandas as pd
import itertools
display(df, summary=True)

Data Wrangler を使って最初のデータ クリーニングを実行する

ノートブック内の pandas データフレームを確認して変換するには、Data Wrangler をノートブックから直接起動します。

Note

ノートブック カーネルがビジー状態の間は、Data Wrangler を開くことができません。 Data Wrangler を起動する前に、セルの実行を完了する必要があります。

  1. ノートブック リボンの [データ] タブで、[Data Wrangler の起動] を選びます。 編集可能でアクティブな pandas データフレームの一覧が表示されます。
  2. Data Wrangler で開くデータフレームを選びます。 このノートブックに含まれる DataFrame は df の 1 つのみなので、df を選びます。

ノートブックから Data Wrangler を起動する方法を示したスクリーンショット。

Data Wrangler が起動し、データを説明する概要が生成されます。 中央のテーブルには、各データ列が表示されます。 テーブルの横にある [概要] パネルには、DataFrame に関する情報が表示されます。 テーブル内の列を選ぶと、選んだ列に関する情報で概要が更新されます。 場合によっては、表示および要約されたデータは、データフレームの一部が切り捨てられたビューになります。 この場合、概要ペインに警告画像が表示されます。 この警告にカーソルを合わせると、状況を説明するテキストが表示されます。

Data Wrangler の概要を示したスクリーンショット。

実行する各操作は、数回クリックするだけで適用でき、リアルタイムでデータ表示を更新し、再利用可能な関数としてノートブックに保存できるコードを生成します。

このセクションの残りの部分では、Data Wrangler でデータ クリーニングを実行する手順について説明します。

重複する行をドロップする

左側のパネルには、データセットに対して実行できる操作一覧 ([検索と置換][書式設定][数式][数値] など) があります。

  1. [検索と置換] を展開し、[重複する行をドロップする] を選びます。

    [検索と置換] に重複する行をドロップする方法を示したスクリーンショット。

  2. 比較する列の一覧を選び、重複する行を定義するためのパネルが表示されます。 RowNumberCustomerId を選びます。

    中央のパネルには、この操作の結果のプレビューが表示されます。 プレビューの下には、操作を実行するコードがあります。 この場合、データは変更されていないように見えます。 ただし、表示されているのは切り捨てられたビューなので、この操作を適用することをお勧めします。

    Data Wrangler で重複する行をドロップする方法を示したスクリーンショット。

  3. [適用] を選んで (横または下部にあります) 次の手順に進みます。

欠損データがある行をドロップする

Data Wrangler を使って、すべての列で欠損データがある行をドロップします。

  1. [検索と置換] から [欠損値をドロップする] を選びます。

  2. [ターゲット] 列から [すべて選択] を選択します。

    Data Wrangler で不足している行をドロップする方法を示したスクリーンショット。

  3. [適用] を選んで次の手順に進みます。

列の削除

Data Wrangler を使って不要な列をドロップします。

  1. [スキーマ] を展開し、[Drop columns] (列のドロップ) を選びます。

  2. RowNumberCustomerIdSurname を選びます。 これらの列は、コードによって変更された (この場合はドロップされた) ことを示すために、プレビューでは赤色で表示されます。

    Data Wrangler の列をドロップする方法を示したスクリーンショット。

  3. [適用] を選んで次の手順に進みます。

ノートブックにコードを追加する

[適用] を選ぶたびに、左下の [Cleaning steps] (クリーニング手順) パネルに新しい手順が作成されます。 パネルの下部にある [すべての手順のコードをプレビューする] を選ぶと、すべての個別手順の組み合わせが表示されます。

左上隅の [ノートブックにコードを追加する] を選ぶと、Data Wrangler が閉じ、コードが自動的に追加されます。 [Add code to notebook] (ノートブックにコードを追加する) を使うと、コードが関数にラップされ、その関数が呼び出されます。

プレビュー コードとノートブックへの追加にアクセスする場所を示したスクリーンショット。

ヒント

Data Wrangler によって生成されたコードは、新しいセルを手動で実行するまで適用されません。

Data Wrangler を使わなかった場合は、代わりにこの次のコード セルを使用できます。

このコードは Data Wrangler によって生成されたコードと似ていますが、生成された各手順に引数 inplace=True が追加されています。 inplace=True を設定することで、pandas は出力として新しいデータフレームを生成する代わりに元のデータフレームを上書きします。

# Modified version of code generated by Data Wrangler 
# Modification is to add in-place=True to each step

# Define a new function that include all above Data Wrangler operations
def clean_data(df):
    # Drop rows with missing data across all columns
    df.dropna(inplace=True)
    # Drop duplicate rows in columns: 'RowNumber', 'CustomerId'
    df.drop_duplicates(subset=['RowNumber', 'CustomerId'], inplace=True)
    # Drop columns: 'RowNumber', 'CustomerId', 'Surname'
    df.drop(columns=['RowNumber', 'CustomerId', 'Surname'], inplace=True)
    return df

df_clean = clean_data(df.copy())
df_clean.head()

データを検索する

クリーンされたデータの概要と視覚化を表示します。

カテゴリ、数値、ターゲットの各属性を決める

このコードを使用して、カテゴリ、数値、ターゲットの各属性を決定します。

# Determine the dependent (target) attribute
dependent_variable_name = "Exited"
print(dependent_variable_name)
# Determine the categorical attributes
categorical_variables = [col for col in df_clean.columns if col in "O"
                        or df_clean[col].nunique() <=5
                        and col not in "Exited"]
print(categorical_variables)
# Determine the numerical attributes
numeric_variables = [col for col in df_clean.columns if df_clean[col].dtype != "object"
                        and df_clean[col].nunique() >5]
print(numeric_variables)

5 つの数値の概要

次のボックス プロットを使って、数値属性の 5 つの数値の概要 (最小スコア、最初の四分位数、中央値、第 3 四分位数、最大スコア) を表示します。

df_num_cols = df_clean[numeric_variables]
sns.set(font_scale = 0.7) 
fig, axes = plt.subplots(nrows = 2, ncols = 3, gridspec_kw =  dict(hspace=0.3), figsize = (17,8))
fig.tight_layout()
for ax,col in zip(axes.flatten(), df_num_cols.columns):
    sns.boxplot(x = df_num_cols[col], color='green', ax = ax)
fig.delaxes(axes[1,2])

5 つの数値の概要を示したグラフ。

離反した顧客と離反していない顧客の分布

次のカテゴリ属性全体の、離反した顧客と離反していない顧客の分布を表示します。

attr_list = ['Geography', 'Gender', 'HasCrCard', 'IsActiveMember', 'NumOfProducts', 'Tenure']
fig, axarr = plt.subplots(2, 3, figsize=(15, 4))
for ind, item in enumerate (attr_list):
    sns.countplot(x = item, hue = 'Exited', data = df_clean, ax = axarr[ind%2][ind//2])
fig.subplots_adjust(hspace=0.7)

離反した顧客と離反していない顧客について表した棒グラフ。

数値属性の分布

ヒストグラムを使用して数値属性の頻度分布を表示します。

columns = df_num_cols.columns[: len(df_num_cols.columns)]
fig = plt.figure()
fig.set_size_inches(18, 8)
length = len(columns)
for i,j in itertools.zip_longest(columns, range(length)):
    plt.subplot((length // 2), 3, j+1)
    plt.subplots_adjust(wspace = 0.2, hspace = 0.5)
    df_num_cols[i].hist(bins = 20, edgecolor = 'black')
    plt.title(i)
plt.show()

数値属性の分布を示したグラフ。

特徴エンジニアリングを実行する

特徴エンジニアリングを実行して、現在の属性に基づいて新しい属性を生成します。

df_clean["NewTenure"] = df_clean["Tenure"]/df_clean["Age"]
df_clean["NewCreditsScore"] = pd.qcut(df_clean['CreditScore'], 6, labels = [1, 2, 3, 4, 5, 6])
df_clean["NewAgeScore"] = pd.qcut(df_clean['Age'], 8, labels = [1, 2, 3, 4, 5, 6, 7, 8])
df_clean["NewBalanceScore"] = pd.qcut(df_clean['Balance'].rank(method="first"), 5, labels = [1, 2, 3, 4, 5])
df_clean["NewEstSalaryScore"] = pd.qcut(df_clean['EstimatedSalary'], 10, labels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

Data Wrangler を使用してワンホット エンコードを実行する

Data Wrangler を使って、One-hot エンコードを実行することもできます。 これを行うには、Data Wrangler を開き直します。 今回は df_clean データを選びます。

  1. [数式] を展開し、[One-hot エンコード] を選びます。
  2. One-hot エンコードを実行する列の一覧を選ぶパネルが表示されます。 GeographyGender を選びます。

この生成されたコードをコピーし、Data Wrangler を閉じてノートブックに戻り、新しいセルに貼り付けることができます。 または、左上隅の [Add code to notebook] (ノートブックにコードを追加する) を選ぶと、Data Wrangler が閉じ、コードが自動的に追加されます。

Data Wrangler を使わなかった場合は、代わりにこの次のコード セルを使用できます。

# This is the same code that Data Wrangler will generate
 
import pandas as pd
 
def clean_data(df_clean):
    # One-hot encode columns: 'Geography', 'Gender'
    df_clean = pd.get_dummies(df_clean, columns=['Geography', 'Gender'])
    return df_clean
 
df_clean_1 = clean_data(df_clean.copy())
df_clean_1.head()

探索的データ分析からの観測の概要

  • スペインやドイツに比べ、フランスからの顧客がほとんどですが、スペインはフランスやドイツに比べてチャーン率が最も低くなっています。
  • ほとんどの顧客はクレジット カードを持っています。
  • 年齢とクレジット スコアがそれぞれ、60 歳より上および 400 点未満の顧客がいますが、外れ値と見なすことはできません。
  • 銀行の商品を 2 つ以上持っている顧客はごくわずかです。
  • アクティブでない顧客は、チャーン率が高くなります。
  • 性別と利用期間 (年数) は、銀行口座を閉じるという顧客の決定には影響を与えないようです。

クリーンされたデータの差分テーブルを作成する

このデータは、このシリーズの次のノートブックで使います。

table_name = "df_clean"
# Create Spark DataFrame from pandas
sparkDF=spark.createDataFrame(df_clean_1) 
sparkDF.write.mode("overwrite").format("delta").save(f"Tables/{table_name}")
print(f"Spark dataframe saved to delta table: {table_name}")

次のステップ

このデータを使って機械学習モデルをトレーニングして登録します。