对SeriesGroupBy , apply与transform的区别
SeriesGroupBy
对象是在 Pandas 中使用 groupby
操作后产生的对象,它代表了对数据进行分组后的一组数据。apply
和 transform
是两种不同的方法,用于对 SeriesGroupBy
对象中的数据进行处理,但它们的行为和用途有一些区别。
apply
方法:
apply
方法对每个分组的数据执行自定义函数,然后将每个分组的计算结果合并成一个新的 Series 或 DataFrame。- 它允许你进行更灵活的操作,因为你可以在自定义函数中执行各种计算和操作,包括聚合、过滤、转换等。
- 结果的索引可能与原始数据不对齐,因此你需要谨慎处理索引的情况。
grouped = df.groupby('column')
result = grouped['column_to_process'].apply(custom_function)
transform
方法:
transform
方法对每个分组的数据执行相同的操作,并返回一个具有相同长度和索引的 Series,其中每个元素是相应分组的处理结果。- 它通常用于在分组数据的基础上创建一个新的列,该列包含每个分组内的计算结果,使得结果与原始数据框对齐。
grouped = df.groupby('column')
result = grouped['column_to_process'].transform(same_function)
总之,apply
和 transform
都用于在分组数据上执行操作,但它们的主要区别在于:
apply
允许你执行自定义函数,可以生成不同形状的结果,但需要小心处理索引对齐。transform
通常用于生成与原始数据对齐的新列,它执行相同的操作并返回一个具有相同长度和索引的 Series。
SeriesGroupBy是一个pandas对象,它表示一个按照Series的值进行分组的操作。apply和transform是两种常用的对SeriesGroupBy对象进行函数应用的方法,它们有以下几点区别:
- apply可以对每个分组应用任意函数,包括聚合函数和非聚合函数,返回结果的长度和形状由函数决定。transform只能对每个分组应用返回单个值的函数,或者返回与原分组相同长度的序列的函数,返回结果的长度和形状与原SeriesGroupBy对象相同。
- apply可以同时处理多个列,而transform只能处理单个列。
- apply可以使用字符串函数、函数列表和字典作为参数,而transform只能使用函数作为参数。
下面是一些例子来说明apply和transform的不同:
假设有如下数据:
s |
m |
values |
number |
s1 |
m1 |
a |
3 |
s1 |
m1 |
n |
2 |
s2 |
m3 |
cb |
5 |
s2 |
m3 |
mk |
8 |
s2 |
m4 |
bg |
10 |
s2 |
m4 |
dg |
1 |
s4 |
m2 |
rr |
2 |
s4 |
m2 |
cb |
2 |
s4 |
m2 |
1 |
7 |
如果我们想要计算每个s分组的number的最大值,我们可以使用apply或transform:
df.groupby('s')['number'].apply(max)
输出:
s |
number |
s1 |
3 |
s2 |
10 |
s4 |
7 |
df.groupby('s')['number'].transform(max)
输出:
number |
3 |
3 |
10 |
10 |
10 |
10 |
7 |
7 |
7 |
可以看到,apply返回了一个长度为3的Series,而transform返回了一个长度为9的Series。
如果我们想要将每个分组的values和number拼接起来,我们可以使用apply,但不能使用transform:
def zidingyi(df):
return df['values'] + df['number'].astype('str')
df.groupby(['s']).apply(zidingyi)
输出:
s |
s1 |
s2 |
s4 |
df.groupby(['s']).transform(zidingyi)
输出:
KeyError: 'values'
可以看到,apply可以处理多个列,并返回一个自定义的结果,而transform只能处理单个列,并且要求返回结果与原分组相同长度。
如果我们想要对每个分组应用多个函数,我们可以使用apply,并传入一个字符串函数、函数列表或字典作为参数:
df.groupby(['s'])['number'].apply(['sum', 'mean', 'max'])
输出:
sum |
mean |
max |
|
s1 |
5 |
2.5 |
3 |
s2 |
24 |
6.0 |
10 |
s4 |
11 |
3.6667 |
7 |
def zidingyi(x):
return x + x.mean()
df.groupby(['s'])['number'].apply({'zidingyi': zidingyi, 'max': max})
输出:
TypeError: unhashable type: 'dict'
可以看到,apply可以使用字符串函数或函数列表作为参数,但不能使用字典作为参数。而transform只能使用函数作为参数,不能使用字符串函数、函数列表或字典作为参数。
以上就是我对SeriesGroupBy, apply和transform的区别的一些解释,希望对你有所帮助。如果你想了解更多关于这些方法的细节,你可以参考以下的网页123。
根据你给出的代码,我可以解释一下对于SeriesGroupBy, apply和transform的区别:
首先,我们看一下你的数据:
col1 |
col2 |
1 |
1 |
1 |
2 |
1 |
3 |
2 |
1 |
2 |
2 |
2 |
3 |
然后,我们看一下你的代码:
# 筛选分类groupby('col1')下['col2']的重复值
df_test = pd.DataFrame(
data=np.array([
[1]*3 + [2]*3,
np.repeat([1,2,3], 2)
]).T,
columns=['col'+str(i) for i in range(1,3)]
)
ser_bool_1 = df_test.groupby('col1', group_keys=True)['col2'].apply(lambda x: x.duplicated(keep=False))
ser_bool_2 = df_test.groupby('col1')['col2'].transform(lambda x: x.duplicated(keep=False))
你的目的是筛选分类groupby(‘col1’)下[‘col2’]的重复值,也就是说,你想要找出在每个col1分组中,col2的值是否有重复。你使用了两种方法:apply和transform,它们的结果分别是:
ser_bool_1
输出:
col1 |
1 |
2 |
ser_bool_2
输出:
col2 |
False |
False |
False |
False |
False |
False |
可以看到,两种方法都返回了一个布尔值的Series,表示每个分组中的每个元素是否有重复。但是,它们有以下几点区别:
- apply返回了一个多层索引的Series,其中第一层索引是col1的值,第二层索引是原数据的行号。transform返回了一个单层索引的Series,其中索引是原数据的行号。
- apply返回了一个分组后的Series,其中每个分组都有一个名字(col1的值)。transform返回了一个未分组的Series,其中没有分组名。
- apply返回了一个与原数据不同长度的Series,其中每个分组只有一个元素。transform返回了一个与原数据相同长度的Series,其中每个分组有多个元素。
以上就是我对你的代码和问题的解释,希望对你有所帮助。如果你想了解更多关于apply和transform的细节,你可以参考以下的网页 。