lassence.net

Field notes from the AI frontier

Apply computation within groups in a pandas DataFrame

--- archive: codebook, 2020–2023 · topic: Pandas ---

One useful capability of pandas is to execute computations within groups of a DataFrame. This is achieved using groupby() followed by transform().

# Import libraries
import pandas as pd
import seaborn as sns

# Load sample data in a DataFrame
df = (
    sns.load_dataset('iris')
    .sample(n=12, random_state=24)
    .sort_values('species')
    .reset_index(drop=True)
    [['species', 'sepal_width']]
)
df
speciessepal_width
0setosa3.4
1setosa3.7
2setosa3.2
3setosa3.1
4setosa3.8
5versicolor2.4
6versicolor2.7
7versicolor2.5
8virginica2.9
9virginica2.8
10virginica3.0
11virginica3.4

Compute mean at group-level

To get group-level statistics like mean, sum or count, use transform('function').

# Get group mean
df.assign(mean=
    df.groupby('species').transform('mean')
)
speciessepal_widthmean
0setosa3.43.440000
1setosa3.73.440000
2setosa3.23.440000
3setosa3.13.440000
4setosa3.83.440000
5versicolor2.42.533333
6versicolor2.72.533333
7versicolor2.52.533333
8virginica2.93.025000
9virginica2.83.025000
10virginica3.03.025000
11virginica3.43.025000

Standardize values

You can center values inside a group by substracting the group mean to each row.

# Standardize values
df.assign(standardized=
    df.groupby('species').transform(lambda x: x - x.mean())
)
speciessepal_widthstandardized
0setosa3.4-0.040000
1setosa3.70.260000
2setosa3.2-0.240000
3setosa3.1-0.340000
4setosa3.80.360000
5versicolor2.4-0.133333
6versicolor2.70.166667
7versicolor2.5-0.033333
8virginica2.9-0.125000
9virginica2.8-0.225000
10virginica3.0-0.025000
11virginica3.40.375000

Rank values inside groups

Besides computing group-wise values, you can also rank values within each group.

# Rank values
df.assign(rank=
    df.groupby('species').transform(lambda x: x.rank())
)
speciessepal_widthrank
0setosa3.43.0
1setosa3.74.0
2setosa3.22.0
3setosa3.11.0
4setosa3.85.0
5versicolor2.41.0
6versicolor2.73.0
7versicolor2.52.0
8virginica2.92.0
9virginica2.81.0
10virginica3.03.0
11virginica3.44.0

Error when output has multiple columns

If the result of the transform generates more than 1 column, and you try to assign it to a column of an existing DataFrame, you will encounter an error like ValueError: Wrong number of items passed X, placement implies 1. To avoid this, pass only one column in the result:

df.assign(rank=
    df.groupby('species').transform(lambda x: x.rank()).iloc[:, 0]
)
speciessepal_widthrank
0setosa3.43.0
1setosa3.74.0
2setosa3.22.0
3setosa3.11.0
4setosa3.85.0
5versicolor2.41.0
6versicolor2.73.0
7versicolor2.52.0
8virginica2.92.0
9virginica2.81.0
10virginica3.03.0
11virginica3.44.0