为什么在使用 DataFrameGroupBy.agg 时可以访问传递给聚合函数的系列

我在玩弄我无法解释的对象apply和agg方法时进行了观察DataFrameGroupBy。


介绍


我理解以下代码,但它作为问题的介绍可能很有用。


我正在分组 DataFrame my_df


   key col0 col1

0    1    A    B

1    1    C    D

2    2    E    F

3    2    G    H

按'key'列然后apply按函数


def func(df): 

     return ''.join(df['col0'] + df['col1'])

产生


>>> my_df.groupby('key').apply(func)

key

1    ABCD

2    EFGH

dtype: object

这按预期工作。我可以访问列'col0','col1'因为func使用时传递给的“分组块”apply是数据帧。



我不明白为什么KeyError在使用agg而不是apply使用相同的功能时会引发no 。


>>> my_df.groupby('key').agg(func)                                     

     col0  col1

key            

1    ABCD  ABCD

2    EFGH  EFGH

据我了解,当使用aggthen 时,func会Series 为 的每一列的每个组传递一个my_df,因此df参数应该是类型Series,并且尝试执行df['col0']并且df['col1']应该生成一个KeyError.


为什么会agg产生结果?我的在哪里KeyError?


研究


我确认,df是Series不能被索引与df['col0']和df['col1']与调试。


然而my_df.groupby('key').agg(func)神奇的作品。


设置:


from IPython.core.debugger import Pdb

import sys


def set_trace():

    Pdb().set_trace(sys._getframe().f_back)


def func(df): 

    set_trace() 

    return ''.join(df['col0'] + df['col1'])

用法:


>>> my_df.groupby('key').agg(func)

> <ipython-input-258-9f34bde72bce>(9)func()

      6 

      7 def func(df):

      8      set_trace()

----> 9      return ''.join(df['col0'] + df['col1'])

     10 


ipdb> type(df)

<class 'pandas.core.series.Series'>

ipdb> df

0    A

1    C

Name: col0, dtype: object

ipdb> df['col0']

*** KeyError: 'col0'

ipdb> df['col1']

*** KeyError: 'col1'


皈依舞
浏览 173回答 2
2回答

守候你守候我

它实际上确实引发了一个KeyError你可以在包装访问时看到的try/except:In [23]: def func(df):&nbsp;&nbsp; &nbsp; ...:&nbsp; &nbsp; &nbsp;print(type(df))&nbsp; &nbsp; ...:&nbsp; &nbsp; &nbsp;print(df)&nbsp; &nbsp; ...:&nbsp; &nbsp; &nbsp;print()&nbsp; &nbsp; ...:&nbsp; &nbsp; &nbsp;try:&nbsp; &nbsp; ...:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;df['col0']&nbsp; &nbsp; ...:&nbsp; &nbsp; &nbsp;except KeyError:&nbsp; &nbsp; ...:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;print('[Error]')&nbsp; &nbsp; ...:&nbsp; &nbsp; &nbsp;return ''.join(df['col0'] + df['col1'])&nbsp; &nbsp; ...:&nbsp;&nbsp; &nbsp; ...:In [24]: df.groupby('key').agg(func)<class 'pandas.core.series.Series'>0&nbsp; &nbsp; A1&nbsp; &nbsp; CName: col0, dtype: object[Error]<class 'pandas.core.series.Series'>0&nbsp; &nbsp; A1&nbsp; &nbsp; CName: col0, dtype: object[Error]<class 'pandas.core.series.Series'>0&nbsp; &nbsp; A1&nbsp; &nbsp; CName: 1, dtype: object[Error]<class 'pandas.core.frame.DataFrame'>&nbsp; &nbsp;key col0 col10&nbsp; &nbsp; 1&nbsp; &nbsp; A&nbsp; &nbsp; B1&nbsp; &nbsp; 1&nbsp; &nbsp; C&nbsp; &nbsp; D<class 'pandas.core.frame.DataFrame'>&nbsp; &nbsp;key col0 col12&nbsp; &nbsp; 2&nbsp; &nbsp; E&nbsp; &nbsp; F3&nbsp; &nbsp; 2&nbsp; &nbsp; G&nbsp; &nbsp; H这KeyError似乎被调用函数排除在外,因此它被静音。检查一些源代码表明agg实际上调用了这个函数。从这里它首先进入这个函数,它返回Noneifarg是一个函数(这是我们的情况)。最后它会在这里的地方try / except Exception进行。

猛跑小猪

agg将整个 DataFrame 传递给func. 从文档中,func : 函数、字符串、字典或字符串/函数列表 用于聚合数据的函数。如果是函数,则必须在传递 DataFrame 或传递给DataFrame.apply.我相信这意味着该函数实际上是由 调度的apply,已知它对整个 DataFrame 进行操作。你可以print在里面通过一个简单的调用来公开它func:def func(df):&nbsp; &nbsp; print(type(df))&nbsp; &nbsp; return ''.join(df['col0'] + df['col1'])&nbsp;df.groupby('key').agg(func)<class 'pandas.core.series.Series'><class 'pandas.core.series.Series'><class 'pandas.core.series.Series'><class 'pandas.core.frame.DataFrame'><class 'pandas.core.frame.DataFrame'>Out[87]:&nbsp;&nbsp; &nbsp; &nbsp;col0&nbsp; col1key&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;1&nbsp; &nbsp; ABCD&nbsp; ABCD2&nbsp; &nbsp; EFGH&nbsp; EFGH所以它确实得到了两个 DataFrame 调用。但它也有 3 个带有 Series 参数的调用,我无法解释为什么会这样,也许是一个错误(我无法在任何地方看到它的记录)。好吧,仔细想想,这是我能想到的最好的办法。现在,agg不确定您的函数想要如何处理数据,因此它将尝试两种方法并使用首先作为系列工作的任何输出。这似乎是一个实现细节,但 Series 是第一个用于传入数据的方法。如果这不起作用,则回退是传递一个 DataFrame 并希望它成功。让我看看我是否可以让它在一个例子中工作......from itertools import countc = count(0)def func(x):&nbsp; &nbsp; i = next(c)&nbsp; &nbsp; print(i, type(x))&nbsp; &nbsp; if i <3:&nbsp; &nbsp; &nbsp; &nbsp; return 'xyz'&nbsp; &nbsp; return ((df['col0'] + df['col1']).tolist())df.groupby('key').agg(func)0 <class 'pandas.core.series.Series'>1 <class 'pandas.core.series.Series'>2 <class 'pandas.core.series.Series'>3 <class 'pandas.core.series.Series'>Out[126]:&nbsp;&nbsp; &nbsp; col0&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; col1key&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1&nbsp; &nbsp; xyz&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;xyz2&nbsp; &nbsp; xyz&nbsp; [AB, CD, EF, GH]接下来,改变循环条件,我们有:def func(x):&nbsp; &nbsp; i = next(c)&nbsp; &nbsp; print(i, type(x))&nbsp; &nbsp; if i in {0, 1}:&nbsp; &nbsp; &nbsp; &nbsp; return 'xyz'&nbsp; &nbsp; return ((x['col0'] + x['col1']).tolist())df.groupby('key').agg(func)0 <class 'pandas.core.series.Series'>1 <class 'pandas.core.series.Series'>2 <class 'pandas.core.series.Series'>3 <class 'pandas.core.series.Series'>4 <class 'pandas.core.series.Series'>5 <class 'pandas.core.frame.DataFrame'>6 <class 'pandas.core.frame.DataFrame'>Out[157]:&nbsp;&nbsp; &nbsp; col0 col1key&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;1&nbsp; &nbsp; &nbsp;AB&nbsp; &nbsp;CD2&nbsp; &nbsp; &nbsp;EF&nbsp; &nbsp;GH并且,更改i in {0, 1}为i in {0, 4},0 <class 'pandas.core.series.Series'>1 <class 'pandas.core.series.Series'>2 <class 'pandas.core.series.Series'>3 <class 'pandas.core.series.Series'>4 <class 'pandas.core.frame.DataFrame'>5 <class 'pandas.core.frame.DataFrame'>Out[158]:&nbsp;&nbsp; &nbsp; col0 col1key&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;1&nbsp; &nbsp; xyz&nbsp; xyz2&nbsp; &nbsp; &nbsp;EF&nbsp; &nbsp;GH请注意函数类型的数量如何根据每次返回的内容而变化。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python