我对Pandas在决定数据帧中的选择是原始数据帧的副本还是原始数据的视图时所使用的规则感到困惑。
如果我有,例如,
df = pd.DataFrame(np.random.randn(8,8), columns=list('ABCDEFGH'), index=range(1,9))
我知道query
会返回一份副本,就像
foo = df.query('2 < index <= 5')
foo.loc[:,'E'] = 40
对原始数据框df
无效。我也理解标量或命名切片返回一个视图,以便分配给它们,例如
df.iloc[3] = 70
或
df.ix[1,'B':'E'] = 222
将更改df
。但是当谈到更复杂的案件时,我迷失了方向。例如,
df[df.C <= df.B] = 7654321
更改df
,但
df[df.C <= df.B].ix[:,'B':'E']
没有。
是否有一个简单的规则,熊猫正在使用我刚刚失踪?在这些特定情况下发生了什么;特别是,如何更改满足特定查询的数据帧中的所有值(或值的子集)(正如我在上一个示例中尝试的那样)?
注意:这与this question不同;我读过the documentation,但我没有受到启发。我还阅读了关于这个主题的“相关”问题,但我仍然缺少Pandas正在使用的简单规则,以及我如何应用它 - 例如 - 修改值(或值的子集)在满足特定查询的数据框中。
答案 0 :(得分:92)
这是规则,后续覆盖:
所有操作都会生成副本
如果提供了inplace=True
,它将就地修改;只有一些操作支持此
设置的索引器,例如.loc/.ix/.iloc/.iat/.at
将设置到位。
上传单个dtyped对象的索引器几乎总是一个视图(取决于内存布局,它可能不是这就是为什么这不可靠)。这主要是为了提高效率。 (以上示例适用于.query
;这将始终返回由numexpr
评估的副本
获取多重对象对象的索引器始终是副本。
chained indexing
df[df.C <= df.B].ix[:,'B':'E']
不能保证有效(因此你坚持从不这样做)。
取而代之的是:
df.ix[df.C <= df.B, 'B':'E']
因为更快并且将始终有效
链式索引是2个单独的python操作,因此无法被pandas可靠地拦截(您经常会获得SettingWithCopyWarning
,但这也不是100%可检测的)。您指出的dev docs提供了更全面的解释。