2

问题已编辑,请先阅读编辑。

我正在使用 groupby 方法对数据框中的数据进行分组,然后使用结果来修改数据框(例如,更改其中一列中的 bool 值)我尝试了两种修改方式:

  1. 在 groupby.apply 方法之外修改 df - 这会更改 df 但是当再次进入应用的方法时,这些更改就消失了。

  2. 通过 groupby 应用修改方法来修改 df。这不会更改 df,并且下次我输入应用方法时更改不会生效。

所以无论哪种方式, groupby.apply 总是指原始 df,无论它如何以及是否被修改。

为了显示:

在 [1] 中:

df = DataFrame({'a':[1,1,1,3,3,3],'b':[2,2,2,4,4,4],'c':[True,True,True,True,True,True]})
df
Out[1]:
a   b   c
0    1   2   True
1    1   2   True
2    1   2   True
3    3   4   True
4    3   4   True
5    3   4   True

现在使用 groupby:

In [2]:

def modify(grp):
    if grp.name==1:
        grp.c = False

def print_group(grp):
    print '\ngroup value is:' + str(grp.name) 
    print grp.c

gb = df.groupby('a')
gb.apply(modify);
gb.apply(print_group);

group value is:1
0    True
1    True
2    True
Name: c, dtype: bool

group value is:3
3    True
4    True
5    True
Name: c, dtype: bool

所以没有改变'c'列

现在,如果我在外面修改 df :

In [3]:

df.ix[df.a==1,'c'] = False
df
Out[3]:
a   b   c
0    1   2   False
1    1   2   False
2    1   2   False
3    3   4   True
4    3   4   True
5    3   4   True

In [4]:

gb.apply(print_group);

group value is:1
0    True
1    True
2    True
Name: c, dtype: bool

group value is:3
3    True
4    True
5    True
Name: c, dtype: bool

因此,似乎通过使用 groupby,创建了 df 的副本,并通过 .apply 应用到它的更改,去哪里?这里的引擎盖下发生了什么?以及如何使它在必要时工作?每次我修改df中的元素时再次运行.groupby?这对我来说听起来非常广泛和多余。有人可以解释一下吗?

编辑:

我现在了解使用 groupby 的大多数问题的根源。在我看来,groupby 机制在逻辑上过于模糊,设计鼓励用户错误地使用它。在我看来,使用 pandas 进行数据分析的整个想法是分组和应用。我认为分组是最昂贵的任务,所以我想正确的用法是只分组一次,然后对组做任何你想做的事情。只要组成员没有改变,你就不应该重新组合数据框。设计中也暗示了这个想法,因为您可以保存一个 groupby 对象,这对我来说意味着 pandas 的作者希望只创建一次 groupby 对象。

但是,从我下面的答案以及下面描述的“不一致”来看,这似乎不是正确的用途。我现在开始认为正确的用途是为每个操作重新组合,即使组本身没有改变。我不知道这是否真的重新组合或只是使用作为数据框成员的分组对象。(如果过去进行了相同的分组)。

底线,我错过了使用 groupby 操作,这给了我奇怪的结果,你可以在这里看到:

首先,我定义了以下函数:

In [138]:

from pandas import *
def modify(grp):
    if grp.name==1:
        grp.c = False
    return grp
def print_group(grp):
    print '\ngroup value is:' + str(grp.name) 
    print grp.c

然后,两个类似的操作给了我不同的结果,据称是“不一致”:

在 [165] 中:

df = DataFrame({'a':[1,1,3,3],'b':[2,2,4,4],'c':[True,True,True,True]})
gb = df.groupby('a')
df = gb.apply(modify);
gb.apply(print_group);
df
group value is:1
0    True
1    True
Name: c, dtype: bool
group value is:3
2    True
3    True
Name: c, dtype: bool
Out[165]:
a   b   c
0    1   2   False
1    1   2   False
2    3   4   True
3    3   4   True

在这里,我通过将修改函数的结果分配给它来更改 df,然后我调用打印函数来查看它是否“看到”了变化。可以看出,事实并非如此。

尝试一些不同的东西,得到了不同的结果:

In [168]:

df = DataFrame({'a':[1,1,3,3],'b':[2,2,4,4],'c':[True,True,True,True]})
gb = df.groupby('a')
df.ix[df.a==1,'c'] = False
gb.apply(print_group);
df
group value is:1
0    False
1    False
Name: c, dtype: bool
group value is:3
2    True
3    True
Name: c, dtype: bool
Out[168]:
a   b   c
0    1   2   False
1    1   2   False
2    3   4   True
3    3   4   True

在这里,我创建了一个数据框,创建了一个 groupby 对象,就地更改了数据框(这很重要),然后调用打印函数来查看 groupby 对象是否“看到”了更改。它做了。在这篇文章的前面,它没有(参见原始文章中的 In[3]、In[4] 和 Out[4])

如您所见,这里有些不一致。这是我对所有这些混乱的解释:

  1. 在第一种情况下,当我将修改函数返回的内容分配给 df 时,我实际上在内存中创建了一个新变量。groupby 对象指的是不同的 df 变量,即内存中的不同位置。因此 df 持有与 groupby “看到”不同的信息。

  2. 在第二种情况下,更改是“就地”进行的,即在相同的内存分配中。因此 groupby 看到了 df 看到的。

  3. 在原始情况下(参见 In[3]、In[4] 和 Out[4]),对 df 进行了更改,但在内存中的新位置。所以 groupby 指的是一个地方,而修改后的 df 指的是另一个地方。

似乎通过 df[cond, 'column_name'] 更改数据帧(此处建议不要创建副本而是创建数据帧的视图)可能正在创建视图,但在不同的内存分配中(即df 是在一个内存点中创建的,已更改,并且原始名称被分配了新内存点的位置,留下 groupby 元素指的是现在放弃的内存位置)

这是我可以解释这些结果的唯一方法。希望得到您的确认。对于这种不当使用,我看到的唯一解决方案是每次都调用 groupby。只能希望 df.groupby 将 groupby 对象保存为 df 的成员,因此如果一次又一次地进行相同的 groupby 调用,则不会每次都从头开始调用。

如果我是对的,groupby 元素与 dataframe 之间的链接非常弱,并且无法完全预期几个 dataframe 修改和 groupby 操作的结果。那么解决方案是什么?为每个应用操作运行 groupby?这似乎是多余的..

4

1 回答 1

2

您只需要在函数中返回框架。Apply 获取函数的输出并创建一个(应用数据的)新框架;如果你None在你的函数中返回,那么它使用原来的(如果你不返回一个值,那么你就是隐式返回None

In [22]: def f(x):
   ....:     if x.name == 1:
   ....:         x.c = False
   ....:     return x
   ....: 

In [24]: df.groupby('a').apply(f)
Out[24]: 
   a  b      c
0  1  2  False
1  1  2  False
2  1  2  False
3  3  4   True
4  3  4   True
5  3  4   True
于 2013-08-14T15:21:02.330 回答