如何在Pandas DataFrame的组中应用函数

  • Post category:Python

当我们在 Pandas 中使用 groupby 函数后,可以将 DataFrame 按照某个或一些列进行分类,得到一组新的数据。在这些新的数据组中,我们可以非常容易地对每一个组应用含有自定义函数的操作。本篇攻略将会详细讲解如何在 Pandas DataFrame 的组中应用函数。

目录

  • 简介
  • 函数类型
  • 应用含有单个参数的函数
  • 应用含有多个参数的函数
  • 应用含有多个方法的函数
  • 应用含有自定义参数的函数
  • 结论

简介

在 Pandas 中,groupby() 函数将数据按照某一列分类并创建一个 Pandas GroupBy 对象,然后可以在这个对象上应用函数。我们可以将需要应用的函数包括在 .apply() 函数中,以便在每一组应用。

函数类型

应用于 Pandas GroupBy 对象的函数类型通常有以下几种:

  • 统计函数:如 sum、mean、min、max、count 等。
  • 聚合函数:如 agg 和 aggregate。
  • 变换函数:如 transform。
  • 过滤函数:如 filter。

这里我们主要介绍 agg 和 apply 函数。

应用含有单个参数的函数

例如,在下面的数据中,我们想分别计算男性和女性的平均年龄,这时我们可以使用 Pandas 的 groupby() 函数和 apply() 函数,如下所示:

import pandas as pd

data = pd.DataFrame({'Gender': ['M', 'F', 'M', 'F', 'F'], 'Age': [25, 32, 18, 47, 52]})

result = data.groupby(['Gender'])['Age'].apply(lambda x: x.mean())

在这段代码中,我们按性别分组并计算了每个分组的平均年龄。

应用含有多个参数的函数

有时候,我们需要让自定义函数接受多个参数,下面的代码展示了这种情况:

import pandas as pd

data = pd.DataFrame({'Gender': ['M', 'F', 'M', 'F', 'F'], 'Age': [25, 32, 18, 47, 52], 'Grade': [70, 82, 90, 75, 88]})

def weighted_mean(df, weight_column, value_column):
    """
    计算带权平均数
    """
    weight_total = df[weight_column].sum()
    weighted_elements = df[value_column] * df[weight_column]
    return weighted_elements.sum() / weight_total

result = data.groupby(['Gender']).apply(weighted_mean, weight_column='Grade', value_column='Age')

在这个例子中,我们使用了一个自定义的函数 weighted_mean,这个函数计算的是一个带权平均数,函数接受3个参数,其中 df 是分组后的 DataFrame,weight_column 是计算带权平均数所需要的权值列,value_column 是计算带权平均数所需要的数值列。最后,我们使用 groupby() 对 Gender 列进行分组,并使用 apply() 函数将 weighted_mean 函数作用于每一个组。

应用含有多个方法的函数

我们还可以使用 lamda 函数来创建复杂的计算。例如,我们想将数据按性别分组后,计算每个组的中位数,并将这个中位数减去该组在所有年龄年龄段中的平均中位数,这时候,我们首先定义中位数减平均值的函数:

import pandas as pd

data = pd.DataFrame({'Gender': ['M', 'F', 'M', 'F', 'F'], 'Age': [25, 32, 18, 47, 52], 'Grade': [70, 82, 90, 75, 88]})

def subtract_median(df, value_column):
    """
    计算一个值和其组的中位数之间的差
    """
    median_value = df[value_column].median()
    avg_median_value = df[value_column].median()
    return median_value - avg_median_value

result = data.groupby(['Gender'])['Age', 'Grade'].apply(lambda x: x.apply(subtract_median, value_column='Age'))

在这个例子中,我们使用了一个自定义的函数 subtract_median,这个函数计算的是每个分组中数值列的中位数减去所有分组的此列数值的平均中位数,函数接受两个参数,其中 df 是分组后的 DataFrame,value_column 是所需要的数值列。然后我们使用 apply() 函数将 subtract_median 函数作用于每一个分组。

应用含有自定义参数的函数

有时候,自定义函数需要接受一些自定义参数,下面的代码展示了如何实现这种情况。

import pandas as pd
import numpy as np

data = pd.DataFrame({'Gender': ['M', 'F', 'M', 'F', 'F'], 'Age': [25, 32, 18, 47, 52], 'Grade': [70, 82, 90, 75, 88]})

def weighted_mean(df, weight_column, value_column, adjust=1.0):
    """
    计算带权平均数
    """
    weight_total = df[weight_column].sum()
    weighted_elements = df[value_column] * df[weight_column] / adjust
    return weighted_elements.sum() / weight_total

result = data.groupby(['Gender']).apply(weighted_mean, weight_column='Grade', value_column='Age', adjust=2.0)

在这个例子中,我们将之前的 weighted_mean 函数进行了修改,新增了 adjust 这个参数,并将其默认值设为 1.0。然后,我们在使用 apply() 函数将这个函数作用于分组的同时,传入一个自定义参数 adjust 的值,这里的值设为 2.0。

结论

在 Pandas 中,我们可以使用 groupby() 函数将 DataFrame 按照某个或一些列进行分类,然后对这些分类的数据组应用自定义函数。我们可以使用 apply() 函数,将需要应用的函数包括在其中,以便在每一个组应用。您可以使用自定义函数进行简单的统计,也可以使用更复杂的函数,以按组计算不同的指标。