假设我们有这样一个数据帧:

dataset = pd.DataFrame({'A':[5,5,5,5,5,5],
                        'B':[1,2,3,4,5,6]})
dataset
    A   B
0   5   1
1   5   2
2   5   3
3   5   4
4   5   5
5   5   6

得到1到4的正常切片可以给我们

ds = dataset[1:4]
ds
    A   B
1   5   2
2   5   3
3   5   4

当通过布尔索引获取切片时,我们可以

sliced = dataset.loc[dataset['B'] % 2 == 0]
sliced
    A   B
1   5   2
3   5   4
5   5   6

我正在try 使用通过布尔索引方法获得的切片来编辑原始数据集.当使用普通切片时,它的工作方式与预期相同

ds.loc[1,'A'] = 10
ds
    A   B
1   10  2
2   5   3
3   5   4

dataset
    A   B
0   5   1
1   10  2
2   5   3
3   5   4
4   5   5
5   5   6

但在编辑布尔索引切片时,它不会更改原始切片

sliced.loc[1,'A'] = 10
sliced
    A   B
1   10  2
3   5   4
5   5   6


dataset
    A   B
0   5   1
1   5   2
2   5   3
3   5   4
4   5   5
5   5   6

我在文档中找不到任何关于布尔索引创建副本而不是视图的内容(我甚至不完全确定这是否是正确的术语).我试着将.loc添加到切片中,但似乎没有任何改变.我甚至try 了ds._is_Copy()和Sliced._is_Copy(),但它们都返回相同的内容,即对原始数据帧的弱引用.._is_view似乎几乎是随机返回True或False,但根据源代码,它似乎并不太可靠.

Def is_view(Self)->bool:

"如果我可能是视图,则返回布尔值"

推荐答案

事情是这样的(正如文档所说,例如,在"警告"警告的链接中,您肯定在try 更改子数据帧的内容时看到过很多次.例如,当您try 更改ds个值时,您才看到它.啊,真灵.但有一个警告,告诉你不应该假设它是这样的),Pandas 在索引时不能保证什么是视图,什么是副本.

因此,您不应该修改数据集的切片.因为你不能指望它是一个景观,或者不是.你的两个案子都是错的.第一个错误(修改ds.loc[1,'A'])是错误的,因为您可能会错误地认为您正在使用副本,而事实并非如此.第二个错误(修改sliced.loc[1,'A']是错误的,因为您可能错误地认为您正在使用一个视图,而实际上并非如此.在哪种情况下,您很难预测自己是谁,所以这两个代码对原始dataset的影响是UB.

现在,这里有一些逻辑(但这是反向工程,没有标准化):像1:4这样的切片在这里是一个视图,因为对于Pandas 来说,只返回行的子集很容易.在底层的NumPy数组中,它与切片相同.同样,出于同样的原因, Select 偶数行的::2可能会导致一个视图(现在在我的机器上就是这样).在NumPy中,您只需调整一些步长,就可以从原始的数组中获得这个array.如果你想到C,你就可以用简单的for(char *p=start; p<end; p+=stride)迭代切片数据,只需使用相同的数据,但不同的开始、结束和步幅.那么,如果没有必要,Pandas 为什么要费心复制这些数据呢?制作副本的唯一原因是因为人们不愿意通过更改切片来更改原始数据的风险……但是文档(以及您忽略的警告)明确指出您不应该这样做.

[dataset['B']%2==1]这样的片可能是副本,因为这一次,没有任何方法可以只返回由相同数据组成的数据帧,具有不同的开始、结束和步长.所以Pandas 只需要复制一份.同样,这也无关紧要,因为您不应该修改它,所以不会有不情愿地只更改本地副本的风险.

但即使在这种情况下,你也不能指望它是一个复制品.例如,在您的情况下,这个切片恰好与您使用dataset[1::2]个时得到的切片相同.而这个返回的是一个视图,而不是副本. 所以,你不能发誓,在future ,不会有超级优化的Pandas 版本,能够意识到dataset[dataset.B%2==1]等同于dataset.loc[1::2],并利用这一点来避免昂贵的复制.

所以,长话短说:按照你收到的警告go 做;不要试图修改切片数据帧的内容.取而代之,使用.loc[slice, column]=...语法.

dataset.loc[1:4, 'A']=10
dataset.loc[dataset.B%2==1, 'A']=15

Python相关问答推荐

在matplotlib动画gif中更改配色方案

跟踪我已从数组中 Select 的样本的最有效方法

我必须将Sigmoid函数与r2值的两种类型的数据集(每种6个数据集)进行匹配,然后绘制匹配函数的求导.我会犯错

使用Keras的线性回归参数估计

使用FASTCGI在IIS上运行Django频道

比较2 PD.数组的令人惊讶的结果

numba jitClass,记录类型为字符串

scikit-learn导入无法导入名称METRIC_MAPPING64'

无法通过python-jira访问jira工作日志(log)中的 comments

"使用odbc_connect(raw)连接字符串登录失败;可用于pyodbc"

改进大型数据集的框架性能

joblib:无法从父目录的另一个子文件夹加载转储模型

索引到 torch 张量,沿轴具有可变长度索引

matplotlib + python foor loop

matplotlib图中的复杂箭头形状

Polars Group by描述扩展

一个telegram 机器人应该发送一个测验如何做?""

有没有办法在不先将文件写入内存的情况下做到这一点?

当HTTP 201响应包含 Big Data 的POST请求时,应该是什么?  

Scipy差分进化:如何传递矩阵作为参数进行优化?