python - 是否可以在 pandas groupby 转换中访问列名?
问题描述
我的理想问题是“如何访问 pandas DataFrameGroupBy.transform 中的列?”,但在执行了一些测试(此处显示)之后,我想知道这是否可能。
我想访问列名,就像我可以使用的一样apply
,但使用transform
。
例如,给定这个样本数据:
import numpy as np
import pandas as pd
np.random.seed(123)
numeric_data = np.random.rand(9, 3)
cat_data = [f'grp_{i}' for i in range(1,4)] * 3
df = pd.DataFrame(numeric_data, columns=list('ABC')).assign(D = cat_data)
print(df)
A B C D
0 0.696469 0.286139 0.226851 grp_1
1 0.551315 0.719469 0.423106 grp_2
2 0.980764 0.684830 0.480932 grp_3
3 0.392118 0.343178 0.729050 grp_1
4 0.438572 0.059678 0.398044 grp_2
5 0.737995 0.182492 0.175452 grp_3
6 0.531551 0.531828 0.634401 grp_1
7 0.849432 0.724455 0.611024 grp_2
8 0.722443 0.322959 0.361789 grp_3
我如何使用transform
从 A 中减去 B,然后乘以 C?可能吗?
我知道通过apply可以轻松地通过使用lambda或传递用户定义的函数来实现,如下所示:
def customFunc(grp):
return (grp['A'] - grp['B']) * grp['C']
df.groupby('D').apply(customFunc)
D
grp_1 0 0.093084
3 0.035679
6 -0.000175
grp_2 1 -0.071147
4 0.150817
7 0.076364
grp_3 2 0.142324
5 0.097464
8 0.144529
dtype: float64
但是,输出值是未排序的(如您在内部索引中所见),因此我不能将这个输出原样放在新列中。一个选项是预先使用 apply 对数据框进行排序,但老实说,我并不完全相信它对于 groupby 中具有更复杂组的大数据会按预期工作。使用转换我会感觉更舒服,否则,我认为通过索引将结果合并回 df 更可靠(假设我们有一个唯一的索引)。
如果我尝试对变换使用相同的函数:
df.groupby('D').transform(customFunc)
然后我得到一个错误:KeyError: 'A'
。
groupby.apply
为了检查使用and时引擎盖下发生的事情groupby.transform
,我执行了以下操作:
# Select the target-group
grp = df.groupby('D')
grp.apply(lambda x: type(x))
D
grp_1 (<class 'pandas.core.frame.DataFrame'>, 3)
grp_2 (<class 'pandas.core.frame.DataFrame'>, 3)
grp_3 (<class 'pandas.core.frame.DataFrame'>, 3)
dtype: object
grp.transform(lambda x: type(x))
A B C
0 <property object at 0x7f7dbde619f0> <property object at 0x7f7dbde619f0> <property object at 0x7f7dbde619f0>
1 <property object at 0x7f7dbde619f0> <property object at 0x7f7dbde619f0> <property object at 0x7f7dbde619f0>
2 <property object at 0x7f7dbde619f0> <property object at 0x7f7dbde619f0> <property object at 0x7f7dbde619f0>
3 <property object at 0x7f7dbde619f0> <property object at 0x7f7dbde619f0> <property object at 0x7f7dbde619f0>
4 <property object at 0x7f7dbde619f0> <property object at 0x7f7dbde619f0> <property object at 0x7f7dbde619f0>
5 <property object at 0x7f7dbde619f0> <property object at 0x7f7dbde619f0> <property object at 0x7f7dbde619f0>
6 <property object at 0x7f7dbde619f0> <property object at 0x7f7dbde619f0> <property object at 0x7f7dbde619f0>
7 <property object at 0x7f7dbde619f0> <property object at 0x7f7dbde619f0> <property object at 0x7f7dbde619f0>
8 <property object at 0x7f7dbde619f0> <property object at 0x7f7dbde619f0> <property object at 0x7f7dbde619f0>
如您所见,apply
将子数据框作为组提供给我们,而我不知道确切transform
提供了什么(这是我第一次面对财产)。我还做了进一步的测试:
# Another trials
grp.transform(lambda x: x.shape) # ValueError
grp.transform(lambda x: x['A']) # KeyError
grp.transform(lambda x: x.loc[0]) # KeyError
grp.transform(lambda x: x.iloc[0]) # works (every value get the first value; similar to 'first')
似乎.iloc[]
我可以独立访问每列的值,但我仍然不知道如何访问其中的列transform
(如果可能的话)。
所以,我最后的问题:
- 是否可以访问列名
groupby.transform
以跨列执行计算? - 如果不是,将输出
apply
放回数据框的最佳(可靠)方法是什么?
解决方案
是否可以访问 groupby.transform 中的列名以跨列执行计算?
不可能,.groupby.transform
分别处理每一列,所以不能“看到”其他列,如groupby.apply
.
如果使用,您可以看到它print
:
print (df.groupby('D').transform(lambda x: print(x)))
2 0.980764
5 0.737995
8 0.722443
Name: A, dtype: float64
2 0.684830
5 0.182492
8 0.322959
Name: B, dtype: float64
2 0.480932
5 0.175452
8 0.361789
Name: C, dtype: float64
如果不是,将输出从应用放回数据帧的最佳(可靠)方法是什么?
如果函数不聚合值:
def customFunc(grp):
return (grp['A'] - grp['B']) * grp['C']
df['new'] = df.groupby('D').apply(customFunc).rename('new').reset_index(level=0, drop=True)
print (df)
A B C D new
0 0.696469 0.286139 0.226851 grp_1 0.093084
1 0.551315 0.719469 0.423106 grp_2 -0.071147
2 0.980764 0.684830 0.480932 grp_3 0.142324
3 0.392118 0.343178 0.729050 grp_1 0.035679
4 0.438572 0.059678 0.398044 grp_2 0.150817
5 0.737995 0.182492 0.175452 grp_3 0.097464
6 0.531551 0.531828 0.634401 grp_1 -0.000175
7 0.849432 0.724455 0.611024 grp_2 0.076364
8 0.722443 0.322959 0.361789 grp_3 0.144529
所以工作一样:
df['new'] = (df['A'] - df['B']) * df['C']
print (df)
A B C D new
0 0.696469 0.286139 0.226851 grp_1 0.093084
1 0.551315 0.719469 0.423106 grp_2 -0.071147
2 0.980764 0.684830 0.480932 grp_3 0.142324
3 0.392118 0.343178 0.729050 grp_1 0.035679
4 0.438572 0.059678 0.398044 grp_2 0.150817
5 0.737995 0.182492 0.175452 grp_3 0.097464
6 0.531551 0.531828 0.634401 grp_1 -0.000175
7 0.849432 0.724455 0.611024 grp_2 0.076364
8 0.722443 0.322959 0.361789 grp_3 0.144529
如果使用函数聚合值DataFrame.join
或Series.map
使用一列进行分组:
def customFunc(grp):
return ((grp['A'] - grp['B']) * grp['C']).mean()
df = df.join(df.groupby('D').apply(customFunc).rename('new'), on='D')
def customFunc(grp):
return ((grp['A'] - grp['B']) * grp['C']).mean()
df['new'] = df['D'].map(df.groupby('D').apply(customFunc))
print (df)
A B C D new
0 0.696469 0.286139 0.226851 grp_1 0.042863
1 0.551315 0.719469 0.423106 grp_2 0.052011
2 0.980764 0.684830 0.480932 grp_3 0.128106
3 0.392118 0.343178 0.729050 grp_1 0.042863
4 0.438572 0.059678 0.398044 grp_2 0.052011
5 0.737995 0.182492 0.175452 grp_3 0.128106
6 0.531551 0.531828 0.634401 grp_1 0.042863
7 0.849432 0.724455 0.611024 grp_2 0.052011
8 0.722443 0.322959 0.361789 grp_3 0.128106
或更改功能:
def customFunc(grp):
grp['new'] = ((grp['A'] - grp['B']) * grp['C']).mean()
return grp
df = df.groupby('D').apply(customFunc)
print (df)
A B C D new
0 0.696469 0.286139 0.226851 grp_1 0.042863
1 0.551315 0.719469 0.423106 grp_2 0.052011
2 0.980764 0.684830 0.480932 grp_3 0.128106
3 0.392118 0.343178 0.729050 grp_1 0.042863
4 0.438572 0.059678 0.398044 grp_2 0.052011
5 0.737995 0.182492 0.175452 grp_3 0.128106
6 0.531551 0.531828 0.634401 grp_1 0.042863
7 0.849432 0.724455 0.611024 grp_2 0.052011
8 0.722443 0.322959 0.361789 grp_3 0.128106
推荐阅读
- swiftui - 有什么方法可以在 Struct 和 Class 之间共享全局变量?@Environment 不起作用
- typescript - react-spring - 如何最好地解决打字稿类型检查问题
- firebase - 尝试按照 Firebase for Flutter 教程构建失败(Android Studio)
- haskell - 用于二叉树集的 foldr
- julia - 禁止有关与现有标识符冲突的警告
- bash - 如何通过引用 powerline 包路径在 bash 上启动 powerline(在全局 pyenv 中)?
- html - Bootstrap4 汉堡菜单和链接项对齐
- c# - 如何在 wpf 中使用 SystemInformation.PowerStatus?
- python - 登录页面不断重复并制作菜单
- cdn - 如果网络提供商部署自己的 CDN,那么他们的 CDN 如何与内容提供商的 CDN 配合使用?