我对Pandas在决定数据帧中的选择是原始数据帧的副本还是原始数据的视图时使用的规则感到困惑.
如果我有,例如,
df = pd.DataFrame(np.random.randn(8,8), columns=list('ABCDEFGH'), index=range(1,9))
Run Code Online (Sandbox Code Playgroud)
我明白a query返回一个副本,就像这样
foo = df.query('2 < index <= 5')
foo.loc[:,'E'] = 40
Run Code Online (Sandbox Code Playgroud)
对原始数据帧没有影响df.我也理解标量或命名切片返回一个视图,以便分配给这些,例如
df.iloc[3] = 70
Run Code Online (Sandbox Code Playgroud)
要么
df.ix[1,'B':'E'] = 222
Run Code Online (Sandbox Code Playgroud)
会改变df.但是当谈到更复杂的案件时,我迷失了方向.例如,
df[df.C <= df.B] = 7654321
Run Code Online (Sandbox Code Playgroud)
变化df,但是
df[df.C <= df.B].ix[:,'B':'E']
Run Code Online (Sandbox Code Playgroud)
才不是.
是否有一个简单的规则,熊猫正在使用,我只是缺少?在这些特定情况下发生了什么; 特别是,如何更改满足特定查询的数据帧中的所有值(或值的子集)(正如我在上一个示例中尝试做的那样)?
注意:这与此问题不同 ; 我已经阅读了文档,但没有得到它的启发.我还阅读了关于这个主题的"相关"问题,但我仍然缺少Pandas正在使用的简单规则,以及我如何应用它 - 例如 - 修改值(或值的子集)在满足特定查询的数据框中.
我喜欢熊猫,并且已经使用它多年并且非常自信我能够很好地处理如何对数据帧进行子集并适当地处理视图与副本(尽管我使用了大量的断言来确定).我也知道有很多关于SettingWithCopyWarning的问题,例如如何处理Pandas中的SettingWithCopyWarning? 以及一些最新的指南,当它发生时缠绕你的头,例如在熊猫中理解SettingWithCopyWarning.
但是我也知道具体的事情,例如这个答案的引用不再出现在最近的文档(0.22.0)中,并且许多事情已经被多年来弃用(导致一些不合适的旧的SO答案),并且事情正在继续改变.
最近,在教导大熊猫完成新手的基本常规Python知识,例如避免链式索引(和使用.iloc/ .loc)之后,我仍然很难提供一般的经验法则来了解何时注意SettingWithCopyWarning(例如何时重要)忽略它是安全的).
我个人发现根据一些规则(例如切片或布尔运算)对数据帧进行子集化的特定模式,然后修改该子集,与原始数据帧无关,是比文档建议的更常见的操作.在这种情况下,我们希望修改副本而不是原始副本,并且警告对新手来说是混乱/可怕的.
我知道提前查看视图与副本的关系
并不容易,例如Pandas用来生成视图与副本的规则是什么?
在Pandas中检查数据框是复制还是查看
因此,我正在寻找一个更普遍(初学者友好)问题的答案:何时对子集化数据帧执行操作会影响创建它的原始数据帧,以及它们何时独立?.
我已经在下面创建了一些我认为合理的案例,但我不确定是否存在"陷阱"我是否缺失或是否有更简单的方法来思考/检查这一点.我希望有人可以证实我对以下用例的直觉是正确的,因为它与我上面的问题有关.
import pandas as pd
df1 = pd.DataFrame({'A':[2,4,6,8,10],'B':[1,3,5,7,9],'C':[10,20,30,40,50]})
Run Code Online (Sandbox Code Playgroud)
1)警告:无
原始更改:否
# df1 will be unaffected because we use .copy() method explicitly
df2 = df1.copy()
#
# Reference: docs
df2.iloc[0,1] = 100
Run Code Online (Sandbox Code Playgroud)
2)警告:是(我真的不明白为什么)
原来改变了:没有
# df1 will be unaffected because .query() always returns a copy
#
# …Run Code Online (Sandbox Code Playgroud) 说我有一个数据帧
import pandas as pd
import numpy as np
foo = pd.DataFrame(np.random.random((10,5)))
Run Code Online (Sandbox Code Playgroud)
我从我的数据子集创建另一个数据帧:
bar = foo.iloc[3:5,1:4]
Run Code Online (Sandbox Code Playgroud)
确实bar持有这些元素的副本foo?有没有办法创建view这些数据呢?如果是这样,如果我尝试修改此视图中的数据会发生什么?Pandas是否提供任何类型的写时复制机制?
摘要:这不起作用:
df[df.key==1]['D'] = 1
Run Code Online (Sandbox Code Playgroud)
但这样做:
df.D[df.key==1] = 1
Run Code Online (Sandbox Code Playgroud)
为什么?
再生产:
In [1]: import pandas as pd
In [2]: from numpy.random import randn
In [4]: df = pd.DataFrame(randn(6,3),columns=list('ABC'))
In [5]: df
Out[5]:
A B C
0 1.438161 -0.210454 -1.983704
1 -0.283780 -0.371773 0.017580
2 0.552564 -0.610548 0.257276
3 1.931332 0.649179 -1.349062
4 1.656010 -1.373263 1.333079
5 0.944862 -0.657849 1.526811
In [6]: df['D']=0.0
In [7]: df['key']=3*[1]+3*[2]
In [8]: df
Out[8]:
A B C D key
0 1.438161 -0.210454 -1.983704 0 1
1 …Run Code Online (Sandbox Code Playgroud) 关于链式索引以及特定操作是进行查看还是复制,StackOverflow上有很多问题.(例如,这里或这里).我仍然没有完全理解它,但令人惊讶的部分是官方文档说"没人知道".(!?!??)这是文档中的一个例子; 你能告诉我他们是否真的这么说,或者他们只是在轻浮吗?
def do_something(df):
foo = df[['bar', 'baz']] # Is foo a view? A copy? Nobody knows!
# ... many lines here ...
foo['quux'] = value # We don't know whether this will modify df or not!
return foo
Run Code Online (Sandbox Code Playgroud)
真的吗?对于那个具体的例子,"没人知道"并且这是非确定性的,这是真的吗?在两个不同的数据帧上,这真的会有不同的表现吗?规则真的很复杂吗?或者这个人是否意味着有一个明确的答案,但只是大多数人都没有意识到这一点?
假设我们有以下数据帧:
df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar',
'foo', 'bar', 'foo', 'foo'],
'B' : ['one', 'one', 'two', 'three',
'two', 'two', 'one', 'three'],
'C' : randn(8), 'D' : randn(8)})
Run Code Online (Sandbox Code Playgroud)
如下所示:
> df
A B C D
0 foo one 0.846192 0.478651
1 bar one 2.352421 0.141416
2 foo two -1.413699 -0.577435
3 bar three 0.569572 -0.508984
4 foo two -1.384092 0.659098
5 bar two 0.845167 -0.381740
6 foo one 3.355336 -0.791471
7 foo three 0.303303 0.452966
Run Code Online (Sandbox Code Playgroud)
然后我做以下事情:
df2 = df …Run Code Online (Sandbox Code Playgroud)