问题已被编辑,请先阅读编辑。
我使用groupby方法对数据框中的数据进行分组,然后使用结果修改数据框(例如,更改其中一列中的bool值)我已经尝试过以下两种方式修改:
修改groupby.apply方法之外的df - 这会更改df但是再次输入apply方法时,这些更改就会消失。
通过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机制在逻辑上太模糊,设计鼓励用户使用错误的原因。我看到这个的方式,大熊猫数据分析背后的整个想法是分组和应用。我认为分组是最昂贵的任务,所以我想到正确的用法是只分组一次,然后按照你想要的组进行。只要组成员不改变,您就不应该重新组合数据帧。这个想法也隐含在设计中,因为你可以保存一个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])
正如您所看到的,这里的某些内容非常不一致。以下是我对所有这些混乱的解释:
在第一种情况下,当我分配给df从修改函数返回的内容时,我实际上在内存中创建了一个新变量。 groupby对象是一个不同的df变量,即内存中的不同位置。因此,df持有的信息不同于groupby"看到"。
在第二种情况下,进行了更改" inplace",即在相同的内存分配中。因此,groupby看到了df看到了什么。
在原始情况下(参见[3],在[4]和Out [4]中)对df进行了更改,但是在内存中的新位置。所以groupby引用一个地方,修改后的df指向另一个地方。
似乎用df [cond,' culomn_name']更改数据框架,建议here不创建副本而是创建数据框视图,可能正在创建视图,但是在不同的内存分配中(即df的副本在内存点中进行更改,并且比原始名称分配了新内存点的位置,而groupby元素指的是现在放弃的内存位置)
这是我解释这些结果的唯一方法。希望您的确认。我认为不正确使用的唯一解决方案是每次调用groupby。人们只能希望df.groupby将groupby对象保存为df的成员,因此如果一次又一次地进行相同的groupby调用,则每次都不会从头开始调用它。
如果我是对的,groupby元素与数据帧之间的联系非常弱,并且无法完全预期几个数据帧修改和groupby操作的结果。那么解决方案是什么?为每个应用操作运行groupby?这似乎是多余的..
答案 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