df.groupby(...)。agg(set)与df.groupby(...)相比产生不同的结果.agg(lambda x:set(x))

时间:2018-03-28 14:21:50

标签: python pandas pandas-groupby

回答this question,结果df.groupby(...).agg(set)df.groupby(...).agg(lambda x: set(x))产生了不同的结果。

数据:

df = pd.DataFrame({
       'user_id': [1, 2, 3, 4, 1, 2, 3], 
       'class_type': ['Krav Maga', 'Yoga', 'Ju-jitsu', 'Krav Maga', 
                      'Ju-jitsu','Krav Maga', 'Karate'], 
       'instructor': ['Bob', 'Alice','Bob', 'Alice','Alice', 'Alice','Bob']})

演示:

In [36]: df.groupby('user_id').agg(lambda x: set(x))
Out[36]:
                    class_type    instructor
user_id
1        {Krav Maga, Ju-jitsu}  {Alice, Bob}
2            {Yoga, Krav Maga}       {Alice}
3           {Ju-jitsu, Karate}         {Bob}
4                  {Krav Maga}       {Alice}

In [37]: df.groupby('user_id').agg(set)
Out[37]:
                                class_type                         instructor
user_id
1        {user_id, class_type, instructor}  {user_id, class_type, instructor}
2        {user_id, class_type, instructor}  {user_id, class_type, instructor}
3        {user_id, class_type, instructor}  {user_id, class_type, instructor}
4        {user_id, class_type, instructor}  {user_id, class_type, instructor}

我希望这里有同样的行为 - 你知道我错过了什么吗?

2 个答案:

答案 0 :(得分:10)

好了这里发生的事情is_list_like没有被处理,因为_aggregate中没有elif is_list_like(arg) and arg not in compat.string_types:

is_list_like

请参阅source

这不是None所以它会在调用链上返回results.append(colg.aggregate(a)) 以结束此行:

TypeError

请参阅source

这会将TypeError: 'type' object is not iterable提升为if not len(results): raise ValueError("no results")

然后提出:

_aggregate_generic

请参阅source

因为我们没有结果,我们最终会调用result[name] = self._try_cast(func(data, *args, **kwargs)

请参阅source

然后调用:

(Pdb) n
> c:\programdata\anaconda3\lib\site-packages\pandas\core\groupby.py(3779)_aggregate_generic()
-> return self._wrap_generic_output(result, obj)

(Pdb) result
{1: {'user_id', 'instructor', 'class_type'}, 2: {'user_id', 'instructor', 'class_type'}, 3: {'user_id', 'instructor', 'class_type'}, 4: {'user_id', 'instructor', 'class_type'}}

请参阅source

然后结束为:

set

我正在运行略有不同版本的pandas,但等效的源代码行是https://github.com/pandas-dev/pandas/blob/v0.22.0/pandas/core/groupby.py#L3779

所以基本上因为In [8]: df.groupby('user_id').agg(lambda x: print(set(x.columns))) {'class_type', 'instructor', 'user_id'} {'class_type', 'instructor', 'user_id'} {'class_type', 'instructor', 'user_id'} {'class_type', 'instructor', 'user_id'} Out[8]: class_type instructor user_id 1 None None 2 None None 3 None None 4 None None 不算作函数或者是可迭代的,它只是在系列迭代上调用ctor,在这种情况下是列,你可以在这里看到相同的效果:

lambda

但是当你使用{{1}}这是一个匿名函数时,它按预期工作。

答案 1 :(得分:2)

也许@Edchum评论agg应用python内置函数,将groupby对象视为迷你数据帧,而当传递已定义的函数时,它会将其应用于每一列。举例说明这是通过印刷。

df.groupby('user_id').agg(print,end='\n\n')

 class_type instructor  user_id
0  Krav Maga        Bob        1
4   Ju-jitsu      Alice        1

  class_type instructor  user_id
1       Yoga      Alice        2
5  Krav Maga      Alice        2

  class_type instructor  user_id
2   Ju-jitsu        Bob        3
6     Karate        Bob        3


df.groupby('user_id').agg(lambda x : print(x,end='\n\n'))

0    Krav Maga
4     Ju-jitsu
Name: class_type, dtype: object

1         Yoga
5    Krav Maga
Name: class_type, dtype: object

2    Ju-jitsu
6      Karate
Name: class_type, dtype: object

3    Krav Maga
Name: class_type, dtype: object

...

希望这就是为什么应用set给出的结果如上所述。