[機械学習のはじめ方] Part7: Pandasによるデータフレーム操作

Step 2: Pythonとデータ前処理

機械学習の旅へようこそ!🚀 Step 1では機械学習の基本的な概念を学びましたね。Step 2では、データ分析に欠かせないPythonライブラリと、データをモデルが学習できる形に整える「データ前処理」のスキルを身につけていきましょう。

今回は、データ分析の世界で最も広く使われているライブラリの一つ、Pandasに焦点を当て、その中核機能であるデータフレームの操作方法を学びます。Pandasをマスターすれば、データの読み込み、加工、集計などが驚くほど簡単になりますよ!

1. Pandasとデータフレームって何? 🤔

Pandasは、Pythonでデータを効率的に扱うための強力なライブラリです。特に、表形式のデータを扱うのに優れています。Excelの表のようなものを想像すると分かりやすいかもしれません。

そのPandasの中心的なデータ構造がデータフレーム (DataFrame) です。データフレームは、行と列から成る2次元のラベル付きデータ構造で、異なる型のデータ(数値、文字列、真偽値など)を一つの表の中に持つことができます。

機械学習では、多くの場合、データはCSVファイルやデータベースから読み込まれ、このデータフレームの形で処理されます。だから、Pandasとデータフレームの操作を理解することは、データ分析や機械学習プロジェクトを進める上で必須のスキルなのです! ✨

2. Pandasを使ってみよう! (インストールとインポート)

まずはPandasを使えるように準備しましょう。Pythonのパッケージ管理ツールであるpipを使ってインストールします。ターミナルやコマンドプロンプトで以下のコマンドを実行してください。

pip install pandas

インストールが終わったら、PythonスクリプトやJupyter NotebookでPandasをインポートします。慣例として、pdという別名をつけてインポートするのが一般的です。

import pandas as pd

これでPandasを使う準備が整いました! 🎉

3. データフレームの作成 📊

データフレームを作成する方法はいくつかあります。

3.1. Pythonの辞書から作成

キーが列名、値がリスト(列データ)となる辞書を用意して、pd.DataFrame()に渡します。

import pandas as pd

# データとなる辞書を作成
data = {
    '名前': ['田中', '佐藤', '鈴木', '高橋'],
    '年齢': [25, 32, 19, 41],
    '部署': ['営業', '開発', '人事', '営業']
}

# 辞書からデータフレームを作成
df = pd.DataFrame(data)

print(df)

実行結果:

   名前  年齢  部署
0  田中  25  営業
1  佐藤  32  開発
2  鈴木  19  人事
3  高橋  41  営業

3.2. リストのリストから作成

データのリスト(各要素が1行分)と、列名のリストを別々に指定します。

import pandas as pd

# データとなるリストのリスト
data_list = [
    ['田中', 25, '営業'],
    ['佐藤', 32, '開発'],
    ['鈴木', 19, '人事'],
    ['高橋', 41, '営業']
]

# 列名のリスト
columns_list = ['名前', '年齢', '部署']

# リストからデータフレームを作成
df_from_list = pd.DataFrame(data_list, columns=columns_list)

print(df_from_list)

実行結果は上記と同じになります。

3.3. CSV/Excelファイルから読み込み

実際のデータ分析では、外部ファイルからデータを読み込むことがほとんどです。Pandasはこれらを簡単に行う関数を提供しています。

CSVファイルの読み込み:

import pandas as pd

# 'data.csv' という名前のCSVファイルを読み込む
# encoding='utf-8' や 'shift-jis' などを指定する必要がある場合もあります
# df_csv = pd.read_csv('data.csv', encoding='utf-8')

# 例として、先ほどのデータフレームをCSVに書き出して、それを読み込む
df.to_csv('sample_data.csv', index=False) # index=Falseでインデックスをファイルに書き出さない
df_csv = pd.read_csv('sample_data.csv')

print(df_csv)

Excelファイルの読み込み:

Excelファイルを読み書きするには、追加でライブラリ (openpyxlxlrd) が必要になる場合があります。pip install openpyxl でインストールできます。

import pandas as pd

# Excelファイルを読み込む (例: 'data.xlsx' の 'Sheet1'シート)
# df_excel = pd.read_excel('data.xlsx', sheet_name='Sheet1')

# 例として、先ほどのデータフレームをExcelに書き出して、それを読み込む
df.to_excel('sample_data.xlsx', index=False, sheet_name='社員リスト')
df_excel = pd.read_excel('sample_data.xlsx', sheet_name='社員リスト')

print(df_excel)
💡 pd.read_csv()pd.read_excel() には、ヘッダーの有無、区切り文字の種類、読み込む列の指定など、多くのオプションがあります。詳細は公式ドキュメントを参照してください。

4. データフレームの基本操作 🔍

データフレームを作成したら、まずは中身を確認したり、特定のデータを取り出したりする基本操作を覚えましょう。

4.1. データの確認

データフレームの概要を掴むための便利なメソッドがあります。

メソッド 説明 コード例
df.head(n=5) 最初のn行を表示 (デフォルトは5行) print(df.head())
df.tail(n=5) 最後のn行を表示 (デフォルトは5行) print(df.tail(2))
df.shape データフレームの形状(行数, 列数)をタプルで返す print(df.shape)
df.columns 列名のリスト(Indexオブジェクト)を返す print(df.columns)
df.index 行のインデックス(RangeIndexなど)を返す print(df.index)
df.info() 各列のデータ型、非欠損値の数、メモリ使用量などの要約情報を表示 df.info()
df.describe() 数値列に関する基本的な統計量(件数、平均、標準偏差、最小値、四分位数、最大値)を計算して表示 (include='all'で全列対象) print(df.describe())
print(df.describe(include='all'))
df.dtypes 各列のデータ型を表示 print(df.dtypes)
import pandas as pd

data = {'名前': ['田中', '佐藤', '鈴木', '高橋'], '年齢': [25, 32, 19, 41], '部署': ['営業', '開発', '人事', '営業']}
df = pd.DataFrame(data)

print("--- head() ---")
print(df.head())

print("\n--- shape ---")
print(df.shape) # (4, 3)

print("\n--- info() ---")
df.info()

print("\n--- describe() ---")
print(df.describe())

print("\n--- describe(include='all') ---")
print(df.describe(include='all'))

4.2. 列の選択

特定の列データを取り出すには、列名を指定します。

import pandas as pd

data = {'名前': ['田中', '佐藤', '鈴木', '高橋'], '年齢': [25, 32, 19, 41], '部署': ['営業', '開発', '人事', '営業']}
df = pd.DataFrame(data)

# --- 単一列の選択 (結果は Series) ---
# 方法1: ブラケット記法 []
name_series = df['名前']
print("--- 単一列 (ブラケット記法) ---")
print(name_series)
print(type(name_series)) # <class 'pandas.core.series.Series'>

# 方法2: ドット記法 . (列名がPythonの変数名として有効な場合のみ)
age_series = df.年齢
print("\n--- 単一列 (ドット記法) ---")
print(age_series)

# --- 複数列の選択 (結果は DataFrame) ---
# 列名のリストをブラケット内に渡す
subset_df = df[['名前', '部署']]
print("\n--- 複数列 ---")
print(subset_df)
print(type(subset_df)) # <class 'pandas.core.frame.DataFrame'>
⚠️ 単一列を選択すると Series という1次元のデータ構造が返されます。複数列を選択すると DataFrame が返されます。

4.3. 行の選択 (`loc` と `iloc`)

特定の行データを取り出すには、loc または iloc を使います。

  • loc: ラベル(インデックス名や列名)に基づいて選択します。
  • iloc: 位置(整数のインデックス番号)に基づいて選択します。
import pandas as pd

data = {'名前': ['田中', '佐藤', '鈴木', '高橋'], '年齢': [25, 32, 19, 41], '部署': ['営業', '開発', '人事', '営業']}
df = pd.DataFrame(data, index=['emp01', 'emp02', 'emp03', 'emp04']) # インデックスを自分で設定

print("--- 元のデータフレーム ---")
print(df)

# --- loc を使った選択 (ラベルベース) ---
# 1行選択 (ラベル 'emp02')
row_loc = df.loc['emp02']
print("\n--- loc: 1行選択 ('emp02') ---")
print(row_loc) # 結果は Series

# 複数行選択 (ラベル 'emp01', 'emp03')
rows_loc = df.loc[['emp01', 'emp03']]
print("\n--- loc: 複数行選択 ('emp01', 'emp03') ---")
print(rows_loc) # 結果は DataFrame

# 行と列を同時に選択 (ラベル 'emp02' の '名前' と '年齢')
cell_loc = df.loc['emp02', ['名前', '年齢']]
print("\n--- loc: 行と列を選択 ('emp02', ['名前', '年齢']) ---")
print(cell_loc) # 結果は Series

# スライスで選択 (ラベル 'emp02' から 'emp04' まで)
slice_loc = df.loc['emp02':'emp04'] # locのスライスは終了ラベルも含む
print("\n--- loc: スライス ('emp02':'emp04') ---")
print(slice_loc)

# --- iloc を使った選択 (位置ベース) ---
# 1行選択 (1番目の行、インデックス番号 0)
row_iloc = df.iloc[0]
print("\n--- iloc: 1行選択 (位置 0) ---")
print(row_iloc) # 結果は Series

# 複数行選択 (1番目と3番目の行、インデックス番号 0, 2)
rows_iloc = df.iloc[[0, 2]]
print("\n--- iloc: 複数行選択 (位置 [0, 2]) ---")
print(rows_iloc) # 結果は DataFrame

# 行と列を同時に選択 (1番目の行の、0番目と2番目の列)
cell_iloc = df.iloc[0, [0, 2]]
print("\n--- iloc: 行と列を選択 (位置 0, [0, 2]) ---")
print(cell_iloc) # 結果は Series (名前と部署)

# スライスで選択 (1番目から3番目の手前まで、インデックス番号 0, 1)
slice_iloc = df.iloc[0:2] # ilocのスライスは終了位置を含まない
print("\n--- iloc: スライス (0:2) ---")
print(slice_iloc)

# 全行の特定の列を選択 (全行の1番目の列、'年齢'列)
column_iloc = df.iloc[:, 1]
print("\n--- iloc: 全行の特定列 (位置 1) ---")
print(column_iloc)
💡 lociloc は非常に強力で、様々な組み合わせでデータを選択できます。特にスライスの挙動(終了位置を含むか含まないか)が異なる点に注意しましょう。

4.4. 条件による絞り込み (ブールインデックス)

特定の条件を満たす行だけを抽出する操作は、データ分析で頻繁に行われます。これは「ブールインデックス」と呼ばれる方法で実現できます。

import pandas as pd

data = {'名前': ['田中', '佐藤', '鈴木', '高橋'], '年齢': [25, 32, 19, 41], '部署': ['営業', '開発', '人事', '営業']}
df = pd.DataFrame(data)

# --- 条件式を作成 ---
# 年齢が30歳以上の条件
condition_age = df['年齢'] >= 30
print("--- 年齢 >= 30 の条件 (Boolean Series) ---")
print(condition_age)
# 0    False
# 1     True
# 2    False
# 3     True
# Name: 年齢, dtype: bool

# --- 条件を使って行を抽出 ---
df_filtered_age = df[condition_age]
# または直接条件式を記述
# df_filtered_age = df[df['年齢'] >= 30]
print("\n--- 年齢が30歳以上のデータ ---")
print(df_filtered_age)

# --- 複数の条件を組み合わせる ---
# 部署が'営業' かつ 年齢が30歳未満の条件
# & : AND (かつ)
# | : OR (または)
# ~ : NOT (否定)
condition_multi = (df['部署'] == '営業') & (df['年齢'] < 30)
print("\n--- 部署 == '営業' AND 年齢 < 30 の条件 ---")
print(condition_multi)
# 0     True
# 1    False
# 2    False
# 3    False
# dtype: bool

df_filtered_multi = df[condition_multi]
print("\n--- 部署が'営業' かつ 年齢が30歳未満のデータ ---")
print(df_filtered_multi)

# --- isin() を使った絞り込み ---
# 部署が '営業' または '人事' のデータ
target_departments = ['営業', '人事']
df_filtered_isin = df[df['部署'].isin(target_departments)]
print("\n--- 部署が '営業' または '人事' のデータ ---")
print(df_filtered_isin)
⚠️ 複数の条件を組み合わせる際は、各条件式を括弧 () で囲むことを忘れないでください。演算子の優先順位の問題を避けるためです。

5. データ操作・加工 🔧

データの確認や抽出ができたら、次はデータを加工してみましょう。

5.1. 列の追加・削除

import pandas as pd
import numpy as np # NumPyもよく一緒に使われます

data = {'名前': ['田中', '佐藤', '鈴木', '高橋'], '年齢': [25, 32, 19, 41], '部署': ['営業', '開発', '人事', '営業']}
df = pd.DataFrame(data)
print("--- 元のデータフレーム ---")
print(df)

# --- 列の追加 ---
# 新しい列 '経験年数' を追加 (ここでは仮のデータ)
df['経験年数'] = [3, 10, 1, 15]
print("\n--- '経験年数' 列を追加 ---")
print(df)

# 既存の列から計算して新しい列を追加
df['入社年'] = 2025 - df['経験年数'] # 仮に2025年時点とする
print("\n--- '入社年' 列を追加 ---")
print(df)

# --- 列の削除 ---
# drop() メソッドを使用 (axis=1 で列を指定)
df_dropped = df.drop('入社年', axis=1) # 元のdfは変更されない
print("\n--- '入社年' 列を削除 (元のdfは不変) ---")
print(df_dropped)

# inplace=True を指定すると、元のデータフレームが直接変更される
# df.drop('入社年', axis=1, inplace=True)
# print("\n--- '入社年' 列を削除 (元のdfを変更) ---")
# print(df)

# 複数列の削除
df_dropped_multi = df.drop(['部署', '経験年数'], axis=1)
print("\n--- '部署', '経験年数' 列を削除 ---")
print(df_dropped_multi)

5.2. 欠損値の扱い

データには値がない「欠損値」(NaN: Not a Number と表現されることが多い)が含まれることがよくあります。機械学習モデルは通常、欠損値をそのまま扱えないため、適切に対処する必要があります。

import pandas as pd
import numpy as np

data = {'名前': ['田中', '佐藤', '鈴木', '高橋', '伊藤'],
        '年齢': [25, 32, np.nan, 41, 28], # 鈴木さんの年齢が欠損
        '部署': ['営業', '開発', '人事', np.nan, '開発'], # 高橋さんの部署が欠損
        '経験年数': [3, 10, 1, 15, np.nan]} # 伊藤さんの経験年数が欠損
df_nan = pd.DataFrame(data)
print("--- 欠損値を含むデータフレーム ---")
print(df_nan)

# --- 欠損値の確認 ---
# isnull() または isna() : 各要素が欠損値かどうかを判定 (True/False)
print("\n--- 欠損値の確認 (isnull) ---")
print(df_nan.isnull())

# isnull().sum() : 列ごとの欠損値の数を集計
print("\n--- 列ごとの欠損値の数 ---")
print(df_nan.isnull().sum())

# --- 欠損値の削除 (dropna) ---
# 欠損値を含む行を削除 (デフォルト)
df_dropped_rows = df_nan.dropna()
print("\n--- 欠損値を含む行を削除 ---")
print(df_dropped_rows)

# 欠損値を含む列を削除 (axis=1)
df_dropped_cols = df_nan.dropna(axis=1)
print("\n--- 欠損値を含む列を削除 ---")
print(df_dropped_cols) # 全ての列に欠損があるので空になる

# 特定の列に欠損値がある行のみ削除 (subset)
df_dropped_subset = df_nan.dropna(subset=['年齢'])
print("\n--- '年齢'列に欠損値がある行を削除 ---")
print(df_dropped_subset)

# --- 欠損値の補完 (fillna) ---
# 特定の値で補完 (例: 0で補完)
df_filled_zero = df_nan.fillna(0)
print("\n--- 欠損値を0で補完 ---")
print(df_filled_zero)

# 列ごとに異なる値で補完 (辞書を使用)
fill_values = {'年齢': df_nan['年齢'].mean(), # 年齢は平均値で補完
               '部署': '不明',             # 部署は'不明'で補完
               '経験年数': df_nan['経験年数'].median()} # 経験年数は中央値で補完
df_filled_specific = df_nan.fillna(value=fill_values)
print("\n--- 列ごとに指定した値で補完 ---")
print(df_filled_specific)

# 前の値で補完 (ffill: forward fill)
df_filled_ffill = df_nan.fillna(method='ffill')
print("\n--- 前の値で補完 (ffill) ---")
print(df_filled_ffill)

# 後の値で補完 (bfill: backward fill)
df_filled_bfill = df_nan.fillna(method='bfill')
print("\n--- 後の値で補完 (bfill) ---")
print(df_filled_bfill)
💡 欠損値の処理方法は、データの特性や分析の目的によって最適なものが異なります。削除するのか、何かの値で補完するのか、慎重に検討しましょう。

5.3. データ型の変換 (`astype`)

列のデータ型を確認し、必要に応じて変換します。例えば、数値として扱いたい列が文字列型になっている場合などです。

import pandas as pd

data = {'商品ID': ['001', '002', '003'],
        '価格': ['500', '1200', '300'], # 文字列型になっている
        '在庫数': [10, 5, 20]}
df_types = pd.DataFrame(data)

print("--- 変換前のデータ型 ---")
print(df_types.dtypes)
# 商品ID     object # objectは通常、文字列型を示す
# 価格       object
# 在庫数       int64
# dtype: object

# '価格'列を数値型 (整数) に変換
df_types['価格'] = df_types['価格'].astype(int)

# '商品ID'列をカテゴリ型に変換 (メモリ効率が良くなることがある)
df_types['商品ID'] = df_types['商品ID'].astype('category')

print("\n--- 変換後のデータ型 ---")
print(df_types.dtypes)
# 商品ID    category
# 価格         int64
# 在庫数       int64
# dtype: object

# 型変換後のデータで計算が可能になる
print("\n--- 合計価格 ---")
print(df_types['価格'].sum()) # 2000

5.4. 集計 (`groupby`, `agg`)

特定の列の値に基づいてデータをグループ化し、グループごとに集計(合計、平均、件数など)を行う操作は非常に強力です。

import pandas as pd

data = {'部署': ['営業', '開発', '人事', '営業', '開発', '開発'],
        '名前': ['田中', '佐藤', '鈴木', '高橋', '伊藤', '渡辺'],
        '年齢': [25, 32, 19, 41, 28, 35],
        '給与': [500, 700, 400, 600, 650, 750]} # 単位は万円(仮)
df_group = pd.DataFrame(data)
print("--- 元のデータフレーム ---")
print(df_group)

# --- groupby() によるグループ化 ---
# 部署ごとにグループ化
grouped_dep = df_group.groupby('部署')

# --- グループごとの集計 ---
# 部署ごとの平均年齢
mean_age_by_dep = grouped_dep['年齢'].mean()
print("\n--- 部署ごとの平均年齢 ---")
print(mean_age_by_dep)

# 部署ごとの合計給与と人数 (size)
sum_salary_by_dep = grouped_dep['給与'].sum()
count_by_dep = grouped_dep.size() # size()はグループごとの行数を返す
print("\n--- 部署ごとの合計給与 ---")
print(sum_salary_by_dep)
print("\n--- 部署ごとの人数 ---")
print(count_by_dep)

# --- agg() を使った複数の集計 ---
# 部署ごとに、年齢の平均と給与の合計・最大値を計算
agg_result = grouped_dep.agg(
    平均年齢=('年齢', 'mean'),
    合計給与=('給与', 'sum'),
    最大給与=('給与', 'max'),
    人数=('名前', 'count') # '名前'列で人数をカウント
)
print("\n--- agg() を使った複数集計 ---")
print(agg_result)

# 集計結果をリセットして通常のデータフレームに戻す (reset_index)
agg_result_reset = agg_result.reset_index()
print("\n--- 集計結果 (reset_index) ---")
print(agg_result_reset)
💡 agg() には、集計したい列名と適用したい集計関数(文字列 or NumPy関数など)を指定します。集計結果の列名を指定することも可能です (例: 平均年齢=('年齢', 'mean'))。

5.5. ソート (`sort_values`)

特定の列の値に基づいてデータフレームの行を並び替えます。

import pandas as pd

data = {'部署': ['営業', '開発', '人事', '営業', '開発', '開発'],
        '名前': ['田中', '佐藤', '鈴木', '高橋', '伊藤', '渡辺'],
        '年齢': [25, 32, 19, 41, 28, 35]}
df_sort = pd.DataFrame(data)
print("--- 元のデータフレーム ---")
print(df_sort)

# --- 年齢で昇順ソート (デフォルト) ---
df_sorted_age_asc = df_sort.sort_values(by='年齢')
print("\n--- 年齢で昇順ソート ---")
print(df_sorted_age_asc)

# --- 年齢で降順ソート ---
df_sorted_age_desc = df_sort.sort_values(by='年齢', ascending=False)
print("\n--- 年齢で降順ソート ---")
print(df_sorted_age_desc)

# --- 複数のキーでソート (部署で昇順、部署が同じなら年齢で降順) ---
df_sorted_multi = df_sort.sort_values(by=['部署', '年齢'], ascending=[True, False])
print("\n--- 部署(昇順) -> 年齢(降順) でソート ---")
print(df_sorted_multi)

5.6. 結合 (`merge`, `concat`)

複数のデータフレームを結合する方法も重要です。

  • pd.merge(): データベースのJOINのように、共通のキー列に基づいてデータフレームを横方向に結合します。
  • pd.concat(): データフレームを縦方向または横方向に単純に連結します。
import pandas as pd

# --- merge の例 ---
df_employees = pd.DataFrame({
    '社員ID': [1, 2, 3, 4],
    '名前': ['田中', '佐藤', '鈴木', '高橋'],
    '部署ID': [10, 20, 10, 30]
})

df_departments = pd.DataFrame({
    '部署ID': [10, 20, 30, 40],
    '部署名': ['営業部', '開発部', '人事部', '総務部']
})

print("--- 社員データ ---")
print(df_employees)
print("\n--- 部署データ ---")
print(df_departments)

# 部署IDをキーにして内部結合 (両方のDFに存在するキーのみ)
df_merged_inner = pd.merge(df_employees, df_departments, on='部署ID', how='inner')
print("\n--- 内部結合 (inner merge) ---")
print(df_merged_inner)

# 左外部結合 (左のDFのキーをすべて残す)
df_merged_left = pd.merge(df_employees, df_departments, on='部署ID', how='left')
print("\n--- 左外部結合 (left merge) ---")
print(df_merged_left) # 高橋さんの部署ID 30 は部署データにあるが、鈴木さんの部署ID 10も残る

# 右外部結合 (右のDFのキーをすべて残す)
df_merged_right = pd.merge(df_employees, df_departments, on='部署ID', how='right')
print("\n--- 右外部結合 (right merge) ---")
print(df_merged_right) # 総務部(ID 40)の情報が残り、対応する社員情報はNaNになる

# 完全外部結合 (両方のDFのキーをすべて残す)
df_merged_outer = pd.merge(df_employees, df_departments, on='部署ID', how='outer')
print("\n--- 完全外部結合 (outer merge) ---")
print(df_merged_outer)


# --- concat の例 ---
df1 = pd.DataFrame({'A': ['A0', 'A1'], 'B': ['B0', 'B1']})
df2 = pd.DataFrame({'A': ['A2', 'A3'], 'B': ['B2', 'B3']})
df3 = pd.DataFrame({'C': ['C0', 'C1'], 'D': ['D0', 'D1']})

print("\n--- df1 ---")
print(df1)
print("--- df2 ---")
print(df2)
print("--- df3 ---")
print(df3)

# 縦方向に連結 (デフォルト axis=0)
df_concat_rows = pd.concat([df1, df2])
print("\n--- 縦方向連結 (concat axis=0) ---")
print(df_concat_rows)

# インデックスを振り直す
df_concat_rows_reset = pd.concat([df1, df2], ignore_index=True)
print("\n--- 縦方向連結 (ignore_index=True) ---")
print(df_concat_rows_reset)

# 横方向に連結 (axis=1)
df_concat_cols = pd.concat([df1, df3], axis=1)
print("\n--- 横方向連結 (concat axis=1) ---")
print(df_concat_cols)

6. まとめと次のステップ 🚀

今回は、データ分析の強力な味方であるPandasライブラリと、その中心的なデータ構造であるデータフレームの基本的な操作方法を学びました。

  • データフレームの作成(辞書、リスト、ファイル読み込み)
  • データの確認(head, info, describe など)
  • データの選択(列選択、行選択 loc/iloc, 条件絞り込み)
  • データの加工(列追加/削除, 欠損値処理, 型変換, 集計 groupby, ソート, 結合)

これらの操作を組み合わせることで、様々な形式のデータを効率的に扱い、分析に適した形に整えることができます。Pandasは非常に多機能なライブラリなので、今回紹介したのはほんの一部です。ぜひ公式ドキュメントなどを参照して、さらに深く学んでみてください。

次は、データを視覚的に理解するためのMatplotlib・Seabornによる可視化の基礎に進みます。データの傾向やパターンをグラフで表現するスキルを身につけましょう!📊📈📉