【问题标题】:groupby objects dont update with updated dataframesgroupby 对象不使用更新的数据框进行更新
【发布时间】:2013-08-14 15:12:18
【问题描述】:

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

我正在使用 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'] 更改数据帧,建议here 不是创建数据帧的副本而是创建数据帧的视图,这可能是在创建一个视图,但在不同的内存分配中(即 df 的副本在内存点中制作,更改后,原始名称被分配到新内存点的位置,留下 groupby 元素引用现在废弃的内存位置)

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

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

【问题讨论】:

    标签: pandas dataframe


    【解决方案1】:

    你只需要在你的函数中返回框架。 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
    

    【讨论】:

    • 对不起,没有完全理解..“如果你在你的函数中返回 NONE 然后它使用原始函数”是什么意思,你的意思是基础数据帧是根据我的 apply 函数确定的返回还是不返回值?我仍然对这里的引擎盖下发生的事情感到困惑。我认为 groupby 对象只是保存所有组及其成员的索引。但这显然不是这样。那么,groupby 对象拥有原始数据帧的副本呢?请详细说明并更清楚..
    • 另外,这意味着为每个应用操作重新组合数据帧,这可能是昂贵且冗余的(请参阅我的编辑......)
    • 也许你可以用一个简单的例子来解释你的问题是什么。优化通常是最后一步。首先确保你有正确性。配置文件,然后根据需要进行优化。 Groupby 是一种廉价的操作;申请可能更贵。但除非你有很多组,否则这无关紧要。
    • 我正在做与您在此处看到的类似的事情,只是规模更大。我有包含重叠索引的组。例如,假设一个由文件索引的数据框,包含两个在索引中重叠的组(即一些文件属于两个组)。现在我正在做一个迭代过程,在每个步骤中,我都会根据一些标准选择文件,然后通过将我的数据框中的“isUsed”列设置为所选文件的 true 来标记已使用的文件。然后我再次选择文件,反之亦然,直到我选择所有文件。
    • 那你为什么不按两列分组呢?如果您的过程是迭代的,那么只需 groupby (并在每次迭代后应用)
    猜你喜欢
    • 2011-08-03
    • 1970-01-01
    • 2020-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-18
    • 2023-03-04
    • 2021-07-08
    相关资源
    最近更新 更多