在Pandas中,transform
和apply
都可以用于对分组数据进行操作,但它们有不同的使用场景和性能特性:
transform
:transform
函数应用于每个分组后,会将结果广播到原始数据的大小,这通常使得transform
更高效。transform
通常会尝试用更高效的内部机制来执行向量化操作。transform
应用的函数应返回标量值或与输入组相同大小的数组。apply
:apply
适用于更复杂的操作,包括改变DataFrame的大小。apply
可以用于执行更多种类的操作,例如,可以返回DataFrame、Series或标量。apply
的通用性通常意味着它在性能上不如transform
高效,尤其是在需要广播结果到原始数据大小的场景。因此,当操作可以使用transform
完成时,通常更推荐使用transform
,以获取更好的性能。当需要更大的灵活性时(例如,改变输出的形状或进行更复杂的计算),则可以使用apply
。
当然,以下是一些应用示例来说明transform
和apply
的不同用途和性能特性。
假设我们有以下DataFrame,它表示三个不同产品在不同日期的销售额:
import pandas as pd
data = {'Date': ['2021-01-01', '2021-01-01', '2021-01-02', '2021-01-02', '2021-01-03', '2021-01-03'],
'Product': ['A', 'B', 'A', 'A', 'B', 'C'],
'Revenue': [100, 150, 200, 50, 300, 400]}
df = pd.DataFrame(data)
transform
进行向量化操作如果我们想要在原DataFrame中添加一个新列,该列表示每个产品的总销售额,我们可以使用transform
:
df['Total_Revenue_By_Product'] = df.groupby('Product')['Revenue'].transform('sum')
transform
将自动广播每个组的结果(即每个产品的总销售额)到该组内所有行。
apply
进行更复杂的操作假设我们想要获得每个产品最高单日销售额的日期,这是一个更复杂的操作,可以使用apply
:
def get_max_revenue_date(group):
return group.loc[group['Revenue'].idxmax(), 'Date']
max_revenue_date = df.groupby('Product').apply(get_max_revenue_date)
这里,apply
允许我们对每个组使用更复杂的函数,并且返回一个与输入形状不同的结果。
通常,在可以使用transform
的场合,使用transform
会更高效。例如,如果我们有一个非常大的DataFrame,使用transform
来计算组平均值通常会比使用apply
更快。
当然,让我说明一下各个示例的输出。
transform
进行向量化操作如果我们运行这段代码:
df['Total_Revenue_By_Product'] = df.groupby('Product')['Revenue'].transform('sum')
df
会被更新,新增了一个列 Total_Revenue_By_Product
,它包含每个产品的总销售额,并会广播到该产品的所有记录。
更新后的 df
如下:
Date Product Revenue Total_Revenue_By_Product
0 2021-01-01 A 100 350
1 2021-01-01 B 150 450
2 2021-01-02 A 200 350
3 2021-01-02 A 50 350
4 2021-01-03 B 300 450
5 2021-01-03 C 400 400
如您所见,产品A、B、和C的总销售额分别是350、450和400,这些值被广播到了每一行对应的产品。
apply
进行更复杂的操作如果我们运行这段代码:
def get_max_revenue_date(group):
return group.loc[group['Revenue'].idxmax(), 'Date']
max_revenue_date = df.groupby('Product').apply(get_max_revenue_date)
max_revenue_date
会是一个 Series
,其中包含每个产品销售额最高的日期:
Product
A 2021-01-02
B 2021-01-03
C 2021-01-03
dtype: object
这里,我们可以看到产品A、B、和C销售额最高的日期分别是 2021-01-02
、2021-01-03
和 2021-01-03
。
当然,下面是另一个使用transform
的例子。这次,我们将计算每个产品的平均销售额,并将该信息添加为新的列。
我们还是使用相同的数据集:
data = {'Date': ['2021-01-01', '2021-01-01', '2021-01-02', '2021-01-02', '2021-01-03', '2021-01-03'],
'Product': ['A', 'B', 'A', 'A', 'B', 'C'],
'Revenue': [100, 150, 200, 50, 300, 400]}
df = pd.DataFrame(data)
transform
计算平均销售额df['Average_Revenue_By_Product'] = df.groupby('Product')['Revenue'].transform('mean')
运行这行代码后,df
会更新,新增一个列Average_Revenue_By_Product
,其中包含每个产品的平均销售额。
更新后的df
会是这样:
Date Product Revenue Average_Revenue_By_Product
0 2021-01-01 A 100 116.666667
1 2021-01-01 B 150 225.000000
2 2021-01-02 A 200 116.666667
3 2021-01-02 A 50 116.666667
4 2021-01-03 B 300 225.000000
5 2021-01-03 C 400 400.000000
如您所见,产品A、B、和C的平均销售额分别是约116.67、225和400,这些值被广播到了每一行对应的产品。