0Pricing
Pandas & NumPy Academy · レッスン

Split-Apply-Combineパターン

groupbyの概念的な流れである、DataFrameをグループに分割し、関数を適用して結果を結合する処理を理解します。

「Split-Apply-Combineパターン」はCoddyKit上の無料Pandas & NumPy Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPandas & NumPy Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Pandas & NumPy Academyコースには全4レッスンが含まれています。

GroupByとは

GroupBy操作は、データ分析で最も強力なパターンの一つです。DataFrameをグループに分割し、各グループに個別に関数を適用して、その結果を新しい構造にまとめられます。このワークフローはsplit-apply-combineパターンと呼ばれ、統計学者のHadley Wickhamが名付けました。

分割ステップ

splitステップでは、Pandasが1列以上の一意な値に基づいてDataFrameをサブDataFrameに分割します。たとえば、region列に'North'、'South'、'West'などの値がある場合、分割ステップによって3つの独立したグループが作成されます。まだデータが移動したりコピーされたりするわけではなく、Pandasはどの行がどのグループに属するかを記録するだけです。

import pandas as pd

df = pd.DataFrame({
    'region': ['North', 'South', 'North', 'West', 'South'],
    'sales': [200, 150, 300, 180, 220]
})

# split: create a GroupBy object
grouped = df.groupby('region')
print(type(grouped))  # DataFrameGroupBy

適用ステップ

applyステップでは、各グループに関数を個別に適用します。関数にはsum()やmean()のような組み込みの集計関数を使うことも、独自に定義したカスタム関数を使うこともできます。各グループの行が関数に渡され、結果としてスカラー、Series、またはDataFrameが返されます。

# apply: compute the sum of 'sales' within each region group
total_sales = grouped['sales'].sum()
print(total_sales)
# region
# North    500
# South    370
# West     180
# Name: sales, dtype: int64

結合ステップ

combineステップでは、Pandasがグループごとの結果を自動的に1つのオブジェクト(通常はSeriesまたはDataFrame)にまとめます。グループキーは結果のインデックスになります。GroupByオブジェクトで集計メソッドを呼び出すと、このステップが内部で実行され、グループごとに1行を持つ見やすい集計表が得られます。

# combine happens automatically — result is a Series indexed by 'region'
print(total_sales.index)   # Index(['North', 'South', 'West'])
print(total_sales.values)  # [500, 370, 180]

GroupByオブジェクトの作成

df.groupby(column)を呼び出すと、GroupByオブジェクトを作成できます。この段階では何も計算されず、遅延評価されるオブジェクトが作られます。これを反復処理してグループを確認したり、集計メソッドをチェーンして計算を開始したりできます。as_index=Falseを渡すと、結果でグループ化列をインデックスではなく通常の列として保持できます。

grouped = df.groupby('region', as_index=False)
result = grouped['sales'].sum()
print(result)
#   region  sales
# 0  North    500
# 1  South    370
# 2   West    180

グループの反復処理

GroupByオブジェクトを反復処理して、各グループを個別に確認できます。反復のたびに(group_key, sub_dataframe)のタプルが返されます。これはデバッグや、任意のPythonコードで各グループを処理したい場合に便利です。ただし、本番環境でのパフォーマンスを重視する場合は、明示的な反復処理よりもベクトル化された集計メソッドを使用してください。

for name, group in df.groupby('region'):
    print(f'--- {name} ---')
    print(group)
# --- North ---
#   region  sales
# 0  North    200
# 2  North    300
# --- South ---
#   region  sales
# 1  South    150
# 4  South    220

一般的な集計関数

PandasのGroupByは、sum()、mean()、count()、min()、max()、std()、median()など、多くの組み込み集計関数に対応しています。これらは高度に最適化されており、すべてのグループを1回のパスで処理します。組み込み関数で対応できる場合は、カスタムPython関数を書くよりも常に組み込み関数を優先してください。

print(df.groupby('region')['sales'].mean())
# region
# North    250.0
# South    185.0
# West     180.0

print(df.groupby('region')['sales'].count())
# region
# North    2
# South    2
# West     1

複数列の同時グループ化

集計メソッドを呼び出す前に複数の列を選択するか、列の選択を省略してすべての数値列を集計することで、複数列に同時に集計を適用できます。結果はSeriesではなくDataFrameになり、集計対象の変数ごとに1列が作成されます。

df2 = pd.DataFrame({
    'region': ['North', 'South', 'North', 'South'],
    'units': [10, 8, 12, 9],
    'revenue': [200, 160, 240, 180]
})

print(df2.groupby('region').sum())
#         units  revenue
# region
# North      22      440
# South      17      340

GroupByのメンタルモデル

GroupByは、SQLのGROUP BY句のようなものだと考えてください。Pandasのdf.groupby('region')['sales'].sum()は、SQLのSELECT region, SUM(sales) FROM df GROUP BY regionと同等です。この対応関係を理解すると、2つのツール間で処理を置き換えやすくなり、パイプラインに適した抽象化を選べるようになります。

# Pandas GroupBy is equivalent to SQL GROUP BY
# SQL:    SELECT region, SUM(sales) FROM df GROUP BY region
# Pandas: df.groupby('region')['sales'].sum()

result = df.groupby('region')['sales'].sum().reset_index()
result.columns = ['region', 'total_sales']
print(result)

ループを使わない理由

一意な値を順番に処理して、統計量を手動で計算すればよいのではないかと疑問に思うかもしれません。その答えはパフォーマンスと可読性です。グループを対象にしたPythonのループは、1回のベクトル化されたgroupby呼び出しよりもはるかに遅く、特に大規模なデータセットではその差が顕著です。GroupBy操作は内部でコンパイル済みのCコードを実行するため、同等のPythonループより10~100倍高速です。

# Slow approach with a loop
results = {}
for region in df['region'].unique():
    subset = df[df['region'] == region]
    results[region] = subset['sales'].sum()

# Fast approach with GroupBy
results_fast = df.groupby('region')['sales'].sum().to_dict()
# Both give the same answer, but GroupBy is orders of magnitude faster

複数のグループキーを使ったGroupBy

より細かい粒度でグループ化する必要がある場合は、リストをgroupby()に渡して複数列でグループ化します。結果にはMultiIndexが作成され、各レベルが1つのグループ化列に対応します。たとえば'region'と'quarter'の両方でグループ化すると、地域と四半期の組み合わせごとの合計が得られます。

df3 = pd.DataFrame({
    'region': ['North', 'North', 'South', 'South'],
    'quarter': ['Q1', 'Q2', 'Q1', 'Q2'],
    'sales': [200, 300, 150, 220]
})

print(df3.groupby(['region', 'quarter'])['sales'].sum())
# region  quarter
# North   Q1         200
#         Q2         300
# South   Q1         150
#         Q2         220

理解度チェック

このレッスンで学んだsplit-apply-combineパターンの理解度を確認しましょう。

レッスンのまとめ

このレッスンでは、すべてのGroupBy操作の基礎となるsplit-apply-combineパターン、df.groupby()を使ったGroupByオブジェクトの作成方法、そしてsum()やmean()などの組み込み集計を適用してグループごとに1つの結果を得る方法を学びました。次は、単一キーと複数キーによるグループ化を、さらに多くの集計メソッドとともに見ていきます。

よくある質問

「Split-Apply-Combineパターン」レッスンは無料ですか?

はい。「Split-Apply-Combineパターン」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Pandas & NumPy Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Pandas & NumPy Academyコースには全4レッスンが含まれています。

「Split-Apply-Combineパターン」で何を学びますか?

groupbyの概念的な流れである、DataFrameをグループに分割し、関数を適用して結果を結合する処理を理解します。 ブラウザで直接実行するハンズオンコードでPandas & NumPy Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Pandas & NumPy Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのPandas & NumPy Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「Split-Apply-Combineパターン」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このPandas & NumPy Academyレッスンでコードを書いて実行できますか?

はい。すべてのPandas & NumPy Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. Split-Apply-Combineパターン
  2. 単一キーと複数キーによるGroupBy
  3. agg()メソッド
  4. GroupByのTransformとFilter
← Pandas & NumPy Academyに戻る