我的理想问题是“如何在 Pandas 的 DataFrameGroupBy.transform() 函数中访问列?”,但在进行了一些测试后(如下所示),我怀疑这是否可能。
我希望能够像使用 apply 一样访问列名,但是改用 transform 实现。
例如,对于以下示例数据:
我能如何使用
我知道使用apply和lambda或传递用户定义函数可以轻松实现这一点,例如:
输出的数值是无序的(如您可以在内部索引中看到),所以我不能将该输出直接放置在新列中。一种选择是使用apply事先对数据框进行排序,但说实话,对于具有更复杂的groupby组的大型数据,我不完全有信心这样做会按预期工作。我更愿意使用transform,否则,我认为通过索引将结果合并回df更可靠(假设我们拥有唯一的索引)。
如果我尝试使用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组的大型数据,我不完全有信心这样做会按预期工作。我更愿意使用transform,否则,我认为通过索引将结果合并回df更可靠(假设我们拥有唯一的索引)。
如果我尝试使用transform来使用相同的函数:
df.groupby('D').transform(customFunc)
接着我遇到了一个错误:KeyError: 'A'
。
为了深入了解使用groupby.apply
和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
的输出放回数据框的最佳(可靠)方式是什么?
df["result"] = (df["B"] - df["A"])*df["C"]
来完成这个操作。您能展示一下实际需要分组的示例吗? - Anakhand* C
替换为* np.mean(C)
以使分组有意义。 - Cainã Max Couto-Silva