You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas不同数据类型列切片:视图还是副本?相关疑问解析

pandas视图与副本问题解析

原始数据准备

import pandas as pd
df = pd.DataFrame([[1,2.0],[3,4.0]], index = ['row1','row2'], 
        columns = ['a','b'])
df2 = df.iloc[:, :]
df3 = df.iloc[:1, :]
df4 = df.iloc[:, :1]

其中列a为int类型,列b为float类型。


问题1:df2、df3、df4是视图还是副本?

测试1结果分析

执行以下代码:

print(df._is_view, df._is_copy)
print(df2._is_view, df2._is_copy)
print(df3._is_view, df3._is_copy)
print(df4._is_view, df4._is_copy)

输出:

False None
False None
False <weakref at 0x7fed1113de90; to 'DataFrame' at 0x7fed11aa80a0>
True <weakref at 0x7fed114d65c0; to 'DataFrame' at 0x7fed11aa9ab0>

要明确两个内部标记的实际含义:

  • _is_view:标记当前对象是否是原数据的子集视图且直接共享内存。全量切片、连续行切片不会被标记为视图,因此df2、df3的_is_view为False。
  • _is_copy:标记当前对象是否由父对象切片衍生而来,df3、df4都指向原df的弱引用,说明二者都是切片衍生对象。
  • df4的_is_view为True,是因为它是单一不同类型列的切片,pandas将其认定为原列数据的视图。

测试2结果与矛盾解释

执行以下代码:

df2.loc['row1', 'b'] = 100.0
print(df)
df3.loc['row1', 'a'] = 1000.0
print(df)
df4.loc['row1', 'a'] = 10000.0
print(df)

输出:

a    b
row1  10  2.0
row2   3  4.0
        a    b
row1  100  2.0
row2    3  4.0
        a    b
row1  100  2.0
row2    3  4.0

同时触发SettingWithCopyWarning警告。

矛盾点的核心原因是:pandas的视图/副本不是绝对判定,而是由内存布局和操作类型共同决定:

  1. df2和df3:全量切片或连续行切片的数据在内存中是连续存储块,修改操作直接作用于原数据内存,因此表现为视图行为(修改同步原df);但_is_view为False是因为内部标记的定义更严格,仅将非连续或特定类型切片视为视图。
  2. df4:单一列切片,原df的不同类型列存储在独立内存块中。虽然_is_view标记为视图,但执行修改时,pandas的SettingWithCopy机制会检测到这是切片衍生对象,为避免意外修改原数据,内部自动创建了副本,因此修改的是副本而非原df,原数据不会同步更新。

问题2:SettingWithCopyWarning中的“a copy of a slice”是什么?

  • “a slice”指的是通过df.iloc[:, :1]得到的df4,它是原df的列切片衍生对象。
  • “a copy of a slice”指的是执行修改操作时,pandas内部自动创建的df4的临时副本。你实际修改的是这个副本,而非原df的视图,因此原df数据不会同步变化。
  • 这个警告的作用是提醒:当前修改操作可能没有作用到你预期的原数据上,而是修改了临时副本,避免出现意外的数据不一致问题。

内容的提问来源于stack exchange,提问作者doraemon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 14:05:36