【上級者向け】Pandas Dataframe GroupByで累積最大値を効率的に計算する高度なテクニック

2024-04-02

pandas.core.groupby.DataFrameGroupBy.cummax とは?

例:

以下のDataFrameについて、"A"列と"B"列それぞれについて、グループごとに累積的な最大値を計算してみましょう。

import pandas as pd

df = pd.DataFrame({
    "A": [1, 2, 3, 1, 2, 3],
    "B": [4, 5, 6, 7, 8, 9],
    "group": ["a", "a", "a", "b", "b", "b"]
})

# グループごとに列ごとに累積的な最大値を計算
df_cummax = df.groupby("group").agg({"A": "cummax", "B": "cummax"})

print(df_cummax)

# 出力
#    A  B
# 0  1  4
# 1  2  5
# 2  3  6
# 3  1  7
# 4  2  8
# 5  3  9

出力結果:

  • グループ "a" の "A" 列: 1, 2, 3, 1, 2, 3
  • グループ "a" の "B" 列: 4, 5, 6, 7, 8, 9
  • グループ "b" の "A" 列: 1, 2, 3

各行の値は、その時点までの最大値を表しています。

オプション

cummax 関数には、以下のオプションがあります。

  • axis: 累積方向を指定します。0の場合は行方向、1の場合は列方向です。
  • skipna: True の場合、欠損値は無視されます。
  • inclusive: True の場合、最初の行も累積値に含めます。

例:

# 列方向に累積的な最大値を計算
df_cummax = df.groupby("group").agg({"A": "cummax", "B": "cummax"}, axis=1)

print(df_cummax)

# 出力
#    0  1  2  3  4  5
# 0  1  4  6  9  12  15
# 1  2  5  7  10  13  16
# 2  3  6  9  12  15  18
# 3  1  7  10  13  16  19
# 4  2  8  11  14  17  20
# 5  3  9  12  15  18  21

pandas.core.groupby.DataFrameGroupBy.cummax は、DataFrameの各グループにおいて、列ごとに累積的な最大値を計算する関数です。グループごとの時系列データの分析などに役立ちます。



pandas.core.groupby.DataFrameGroupBy.cummax サンプルコード

import pandas as pd

df = pd.DataFrame({
    "A": [1, 2, 3, 1, 2, 3],
    "B": [4, 5, 6, 7, 8, 9],
    "group": ["a", "a", "a", "b", "b", "b"]
})

# グループごとに列ごとに累積的な最大値を計算
df_cummax = df.groupby("group").agg({"A": "cummax", "B": "cummax"})

print(df_cummax)

出力結果:

    A  B
0  1  4
1  2  5
2  3  6
3  1  7
4  2  8
5  3  9

例2:列方向に累積的な最大値を計算

df_cummax = df.groupby("group").agg({"A": "cummax", "B": "cummax"}, axis=1)

print(df_cummax)

出力結果:

    0  1  2  3  4  5
0  1  4  6  9  12  15
1  2  5  7  10  13  16
2  3  6  9  12  15  18
3  1  7  10  13  16  19
4  2  8  11  14  17  20
5  3  9  12  15  18  21

例3:欠損値を無視して累積的な最大値を計算

df_cummax = df.groupby("group").agg({"A": "cummax", "B": "cummax"}, skipna=True)

print(df_cummax)

出力結果:

    A  B
0  1  4
1  2  5
2  3  6
3  NaN  7
4  NaN  8
5  NaN  9

例4:最初の行も累積値に含める

df_cummax = df.groupby("group").agg({"A": "cummax", "B": "cummax"}, inclusive=True)

print(df_cummax)

出力結果:

    A  B
0  1  4
1  2  5
2  3  6
3  1  7
4  2  8
5  3  9

例5:複数の集計関数を同時に使用

df_cummax = df.groupby("group").agg({"A": "cummax", "B": ["cummax", "mean"]})

print(df_cummax)

出力結果:

       A          B          
       cummax  cummax  mean
0  1.000000  4.000000  4.500000
1  2.000000  5.000000  4.500000
2  3.000000  6.000000  4.500000
3  1.000000  7.000000  7.000000
4  2.000000  8.000000  7.000000
5  3.000000  9.000000  7.000000

例6:lambda式を使用して集計関数を定義

df_cummax = df.groupby("group").agg({"A": lambda x: x.cummax(), "B": lambda x: x.cummax()})

print(df_cummax)

出力結果:

    A  B
0  1  4
1  2  5
2  3  6
3  1  7
4  2  8
5  3  9


pandas.core.groupby.DataFrameGroupBy.cummax 以外の方法

for ループを使用する

def g(df):
    for group in df["group"].unique():
        df_group = df.loc[df["group"] == group]
        df_group["A_cummax"] = df_group["A"].cummax()
        df_group["B_cummax"] = df_group["B"].cummax()
        yield df_group

df = df.groupby("group").apply(g)

print(df)

出力結果:

    group  A  B  A_cummax  B_cummax
0      a  1  4        1        4
1      a  2  5        2        5
2      a  3  6        3        6
3      b  1  7        1        7
4      b  2  8        2        8
5      b  3  9        3        9

NumPy の cummax 関数を使用する

import numpy as np

def g(df):
    df["A_cummax"] = np.cummax(df["A"])
    df["B_cummax"] = np.cummax(df["B"])
    return df

df = df.groupby("group").apply(g)

print(df)

出力結果:

    group  A  B  A_cummax  B_cummax
0      a  1  4        1        4
1      a  2  5        2        5
2      a  3  6        3        6
3      b  1  7        1        7
4      b  2  8        2        8
5      b  3  9        3        9

itertools.groupby と functools.reduce を使用する

from itertools import groupby
from functools import reduce

def g(df):
    for group, rows in groupby(df, lambda x: x["group"]):
        df_group = pd.DataFrame(rows)
        df_group["A_cummax"] = reduce(lambda a, b: a + max(b, 0), df_group["A"])
        df_group["B_cummax"] = reduce(lambda a, b: a + max(b, 0), df_group["B"])
        yield df_group

df = df.groupby("group").apply(g)

print(df)

出力結果:

    group  A  B  A_cummax  B_cummax
0      a  1  4        1        4
1      a  2  5        2        5
2      a  3  6        3        6
3      b  1  7        1        7
4      b  2  8        2        8
5      b  3  9        3        9

これらの方法は、それぞれ異なる長所と短所があります。

  • for ループを使用する方法は、最もシンプルで分かりやすいですが、最も処理速度が遅くなります。
  • NumPy の cummax 関数を使用する方法は、処理速度が最も速くなりますが、NumPy の知識が必要となります。
  • itertools.groupbyfunctools.reduce を使用する方法は、処理速度とコードの簡潔さのバランスが良い方法です。



Pandas データオフセット:Tick オブジェクトを使いこなして時系列データ分析をレベルアップ

この解説では、pandas. tseries. offsets. Tick オブジェクトの copy メソッドについて、以下の内容を詳しく説明します。Tick オブジェクトの概要copy メソッドの機能メソッドの引数と戻り値使用例関連するデータオフセット



pandas Data Offsets: QuarterBegin.is_year_start の詳細

pandas. tseries. offsets. QuarterBegin は、四半期ごとに日付を進めるためのオフセットです。 is_year_start 属性は、四半期の開始が年の開始であるかどうかを示します。デフォルトでは、False に設定されていますが、startingMonth 引数を使用して変更できます。


Pandas BYearEnd オフセットで年末を自在に操る: データ分析の強力な武器

pandas. tseries. offsets. BYearEnd. n は、Pandas データ分析ライブラリで提供される DateOffset クラスの一つであり、年末 を基準とした日付オフセットを定義します。これは、特定の日付から n 年後の年末 を計算するために使用されます。


【完全解説】pandas.tseries.offsets.Week.is_quarter_startの使い方

pandas. tseries. offsets. Week. is_quarter_start は、pandas ライブラリの DateOffset クラスのサブクラスである Week クラスに属するメソッドです。このメソッドは、指定された日付が四半期の最初の週かどうかを判定します。


Stack Overflow での Pandas Nano.rollforward に関する質問と回答

pandas. tseries. offsets. Nano は、ナノ秒単位で日付を調整するためのオフセットです。Nano. rollforward メソッドは、指定された日付を次のナノ秒境界にロールフォワードします。これは、高精度な時間系列データの分析で特に役立ちます。



Pandas DataFrame の replace メソッド vs その他の置換方法: 速度比較と使い分け

pandas. DataFrame. replace メソッドは、DataFrame 内の特定の値を別の値に置き換えるために使用されます。これは、データのクリーニング、欠損値の処理、または単純にデータの値を変更したい場合に役立ちます。基本的な使い方


Pandas DataFrame から Xarray Dataset への変換

pandas. DataFrame. to_xarray() メソッドは、Pandas DataFrame を Xarray Dataset に変換します。これは、データ分析、可視化、モデリングなど、さまざまなタスクで役立ちます。主な利点:


Pandas Series の mod() メソッド:オプション引数で使いこなす

このチュートリアルでは、pandas. Series. mod() メソッドの仕組みと、データ分析やデータ処理における具体的な使い方を、豊富なコード例と図を用いて分かりやすく解説します。目次概要: #概要基本的な使い方: #基本的な使い方 単一の値で割る: #単一の値で割る Seriesで割る: #Seriesで割る DataFrameで割る: #DataFrameで割る


pandas.TimedeltaIndex.to_frame() で時間差データを分かりやすく分析

pandas. TimedeltaIndex. to_frame() は、pandas ライブラリの関数で、TimedeltaIndex オブジェクトを DataFrame オブジェクトに変換します。これは、時間差データを分析する際に非常に便利な機能です。


Pythonで年末判定を簡単に行う: pandas.DatetimeIndex.is_year_end

pandas. DatetimeIndex. is_year_end は、PandasのDatetimeIndexオブジェクトに対して、各日付が年末であるかどうかを判定する便利な属性です。年末判定を効率的に行うことができ、データ分析や可視化において役立ちます。