groupby对象不使用更新的数据帧进行更新

时间:2013-08-14 15:12:18

标签: pandas dataframe

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

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

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

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

  3. 无论哪种方式,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机制在逻辑上太模糊,设计鼓励用户使用错误的原因。我看到这个的方式,大熊猫数据分析背后的整个想法是分组和应用。我认为分组是最昂贵的任务,所以我想到正确的用法是只分组一次,然后按照你想要的组进行。只要组成员不改变,您就不应该重新组合数据帧。这个想法也隐含在设计中,因为你可以保存一个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对象,将数据框改为inplace(这很重要),然后调用打印函数来查看groupby对象"是否看到"改变。它做了。 在这篇文章的前面,它没有(见原帖子中的[3],[4]和[4])

    正如您所看到的,这里的某些内容非常不一致。以下是我对所有这些混乱的解释:

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

    2. 在第二种情况下,进行了更改" inplace",即在相同的内存分配中。因此,groupby看到了df看到了什么。

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

    4. 似乎用df [cond,' culomn_name']更改数据框架,建议here不创建副本而是创建数据框视图,可能正在创建视图,但是在不同的内存分配中(即df的副本在内存点中进行更改,并且比原始名称分配了新内存点的位置,而groupby元素指的是现在放弃的内存位置)

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

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

1 个答案:

答案 0 :(得分: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