Pandas df.groupby() 関数

Pandas 常用関数


groupby()これは Pandas で最も強力なグループ化操作関数の一つであり、1つまたは複数の列の値に基づいてデータを異なるグループに分割し、各グループに対してさまざまな操作を行うことができます。

簡単に言うと、groupby()実現するのは「分割-適用-結合」(Split-Apply-Combine)というワークフローです:まず条件に応じてデータを分割し、各グループに関数を適用し、最後に結果を結合します。

これはデータ分析で非常に一般的で、例えば部門ごとの従業員の平均給与の集計、月ごとの売上の集計、地域ごとのユーザー数の集計などに使用されます。


基本構文とパラメータ

groupby()は DataFrame のメンバー関数であり、ドット演算子.を使用して呼び出します。呼び出した後は、GroupByオブジェクトが返されます。このオブジェクト自体は結果を直接表示せず、集約関数と組み合わせて使用する必要があります。

構文形式

DataFrame.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False, observed=False, dropna=True)

パラメータの説明

パラメータ 型 説明 デフォルト値
by str、list または dict グループ化に使用する列名または列名のリスト。辞書または関数の場合は、その結果に基づいてグループ化されます。 None
axis int グループ化の軸方向。0 は行方向(デフォルト)、1 は列方向を表します。 0
level int または str マルチインデックス(MultiIndex)の場合は、指定したレベルでグループ化します。 None
as_index bool True の場合、グループ化列は戻り値のインデックスになります。False の場合、グループ化列は通常の列として保持されます。 True
sort bool グループラベルを並べ替えるかどうか。False に設定するとパフォーマンスが向上します。 True
group_keys bool 呼び出すapply()ときに、結果にグループキーをインデックスとして追加するかどうか。 True
observed bool True の場合、カテゴリ変数の実際の観測値のみが表示され、可能なすべての値は表示されません。 False
dropna bool True の場合、NA/null 値を含むグループは破棄されます。 True

戻り値

  • 戻り値の型:DataFrameGroupBy 或 SeriesGroupByオブジェクト
  • 説明:返されるのはグループオブジェクトであり、最終結果ではありません。後続で集約関数(例:sum()、mean()、count()など)を呼び出して、具体的な計算結果を得る必要があります。

例

簡単なものから複雑なものまでの一連の例を通じて、groupby()の使い方を徹底的にマスターしましょう。

例1:単一列によるグループ化

最も基本的な使い方は、ある列の値に基づいてグループ化することです。販売データテーブルがあり、地域ごとに総売上額を集計する必要があるとします。

例

import pandas as pd

# 簡単な販売データの DataFrame を作成する
# 地域、製品、売上高を含む表をシミュレートする
data = {
    '地区': ['华北', '华东', '华南', '华北', '华东', '华南', '华北', '华东'],
    '产品': ['A', 'B', 'C', 'B', 'A', 'C', 'A', 'B'],
    '销售额': [1000, 2000, 1500, 1800, 2200, 1600, 1200, 2100]
}

# 创建 DataFrame
df = pd.DataFrame(data)

print("原始数据:")
print(df)
print()

# 「地区」列でグループ化し、各地区の総売上高を計算する
# as_index=True は地区をインデックスとして返します
grouped = df.groupby('地区', as_index=True)['销售额'].sum()

print(地区別にグループ化した後の総売上高:)
print(grouped)
print()

# as_index=False の場合、グループ化列は通常の列として保持されます。
grouped_df = df.groupby('地区', as_index=False)['销售额'].sum()

print("as_index=False の場合の結果:")
print(grouped_df)

実行結果の想定:

原始数据:
  地区  产品   销售额
0  华东   B   2000
1  华南   C   1500
2  华北   A   1000
3  华东   B   1800
4  华南   C   2200
5  华北   A   1600
6  华东   A   1200
7  华南   B   2100

按地区分组后的总销售额:
地区
华东    7100
华南    7300
华北    3600
dtype: int64

as_index=False 时的结果:
   地区    销售额
0  华东    7100
1  华南    7300
2  华北    3600

コードの解説:

  1. df.groupby('地区')「地区」列の値に従ってデータを「华东」「华南」「华北」の3つのグループに分割します。
  2. ['销售额'].sum()「销售额」列のみに対して合計集約を行うことを意味します。
  3. as_index=True(デフォルト値)の場合、返される Series は「地区」をインデックスとします;as_index=Falseの場合、返される DataFrame は「地区」を通常の列として保持し、後続の処理に適しています。

例2:複数列によるグループ化

複数の列で同時にグループ化する必要がある場合があります。例えば、地域と製品ごとに売上を集計する場合です。

例

import pandas as pd

# 创建销售数据
data = {
    '地区': ['华北', '华东', '华南', '华北', '华东', '华南', '华北', '华东'],
    '产品': ['A', 'B', 'C', 'B', 'A', 'C', 'A', 'B'],
    '销售额': [1000, 2000, 1500, 1800, 2200, 1600, 1200, 2100]
}
df = pd.DataFrame(data)

print("原始数据:")
print(df)
print()

# 「地区」と「製品」の2列でグループ化し、総売上高を計算する
# 使用列表指定多个分组列
grouped = df.groupby(['地区', '产品'], as_index=False)['销售额'].sum()

print(地域と製品ごとにグループ化した後の総売上高:)
print(grouped)
print()

# 使用 pivot_table 更直观地展示结果
pivot = df.pivot_table(values='销售额', index='地区', columns='产品', aggfunc='sum', fill_value=0)
print("使用 pivot_table 展示:")
print(pivot)

実行結果の想定:

原始数据:
  地区  产品   销售额
0  华北   A   1000
1  华东   B   2000
2  华南   C   1500
3  华北   B   1800
4  华东   A   2200
5  华南   C   1600
6  华北   A   1200
7  华东   B   2100

按地区和产品分组后的总销售额:
   地区  产品   销售额
0  华东   A   2200
1  华东   B   4100
2  华南   C   3100
3  华北   A   2200
4  华北   B   1800

使用 pivot_table 展示:
产品      A     B     C
地区
华北   2200  1800     0
华东   2200  4100     0
华南      0     0  3100

コードの解説:

  • ['地域', '製品']リストを使用すると複数の列で同時にグループ化でき、結果は多階層インデックスになります。
  • as_index=Falseの場合、グループ化列は通常の列として結果に保持され、確認や後続の処理が容易になります。
  • pivot_table()pivot_table は同様のクロス集計機能を提供し、グループ化結果をより直感的に表示できます。

例3:辞書と関数を使ったグループ化

groupby()列名によるグループ化だけでなく、辞書や関数を使ってグループ化ルールを定義することもできます。これはカスタムのグループ化ロジックが必要な場合に非常に便利です。

例

import pandas as pd

# 创建学生成绩数据
data = {
    '姓名': ['张三', '李四', '王五', '赵六', '孙七', '周八'],
    '语文': [85, 92, 78, 88, 95, 82],
    '数学': [90, 85, 92, 78, 88, 91],
    '英语': [88, 90, 85, 92, 87, 89]
}
df = pd.DataFrame(data)

print("原始学生成绩数据:")
print(df)
print()

# 1. 使用字典进行自定义分组
# 「姓氏」に基づいてグループ化すると仮定します(張、李、王は1つのグループ、趙、孫、周は別のグループ)
def get_surname_group(name):
    """根据姓氏返回分组名称"""
    if name in ['张三', '李四', '王五']:
        return '第一组'
    else:
        return '第二组'

# 使用 apply 函数进行分组
grouped = df.groupby(get_surname_group).mean(numeric_only=True)
print("使用函数自定义分组(计算每组平均分):")
print(grouped)
print()

# 2. 辞書を使用して特定の列のグループ化をマッピングする
# 数値区間に基づいて国語の成績を「優秀」と「良好」の2つのグループに分ける
score_mapping = {
    '语文': lambda x: '优秀' if x >= 90 else '良好'
}

# 国語列を条件でグループ化
grouped_by_score = df.groupby(lambda x: '优秀' if df.loc[x, '语文'] >= 90 else '良好').mean(numeric_only=True)
print("国語の成績でグループ化(>=90は優秀):")
print(grouped_by_score)

実行結果の想定:

原始学生成绩数据:
   姓名  语文  数学  英语
0  张三   85   90   88
1  李四   92   85   90
2  王五   78   92   85
3  赵六   88   78   92
4  孙七   95   88   87
5  周八   82   91   89

使用函数自定义分组(计算每组平均分):
              语文     数学     英语
姓名
第一组  85.000000  89.000000  87.666667
第二组  88.333333  85.666667  89.333333

按语文成绩分组(>=90为优秀):
              语文     数学     英语
语文
优秀   93.500000  86.500000  88.500000
良好   83.250000  89.500000  88.750000

コードの解説:

  • カスタム関数によるグループ化は、関数がグループ化に使用する値を返すだけで、複雑なグループ化ロジックを処理できます。
  • 使用numeric_only=Trueパラメータを使用すると、数値列のみに対して集約計算を行い、非数値列(例:姓名)に対する操作時のエラーを回避できます。
  • 辞書マッピングを使用すると、「条件に応じて異なる列を異なるグループに分割する」という要件を実現できます。

例4:グループ化後の反復処理

場合によっては、各グループに対してより複雑なカスタム操作を行う必要があり、その場合はグループオブジェクトを反復処理できます。

例

import pandas as pd

# 创建销售数据
data = {
    '地区': ['华北', '华东', '华南', '华北', '华东', '华南'],
    '产品': ['A', 'B', 'C', 'B', 'A', 'C'],
    '销售额': [1000, 2000, 1500, 1800, 2200, 1600]
}
df = pd.DataFrame(data)

print("生データ:")
print(df)
print()

# 各グループを走査して処理する
print("各グループの詳細情報:")
print("-" * 40)

for group_name, group_data in df.groupby('地区'):
    print(f"\nグループ名: {group_name}")
    print(f"このグループのデータ行数: {len(group_data)}")
    print(f"このグループの売上総額: {group_data['销售额'].sum()}")
    print(f"このグループの平均売上額: {group_data['销售额'].mean():.2f}")
    print("-" * 40)

実行結果の予想:

原始数据:
  地区  产品   销售额
0  华东   B   2000
1  华南   C   1500
2  华北   A   1000
3  华东   B   1800
4  华南   C   2200
5  华北   B   1800

每个分组的详细信息:
----------------------------------------

分组名称: 华东
该组数据行数: 2
该组销售总额: 3800
该组平均销售额: 1900.00
----------------------------------------

分组名称: 华南
该组数据行数: 2
3700
1850.00
----------------------------------------

分组名称: 华北
该组数据行数: 2
2800
1400.00
----------------------------------------

コード解析:

  • groupby()返されたグループオブジェクトは直接反復処理できます。各反復処理では、タプル(グループ名、そのグループのデータ)が返されます。
  • この方法を使用すると、各グループに対して任意の複雑なカスタム操作を実行できます。
  • 実際のアプリケーションでは、この方法は複雑なレポートの生成やデータクレンジングによく使用されます。

ヒント:groupby()返された GroupBy オブジェクトは「遅延実行」であり、結果をすぐには計算しません。集約関数を呼び出した場合のみ(例:sum()、mean()、count()など)または反復処理を行った場合にのみ、実際に計算が実行されます。


Pandas 常用関数

その他の拡張