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

Pandas中.loc/.iloc返回副本而非视图的原因及视图获取方法

Pandas DataFrame列子集返回视图而非副本的问题

问题描述

我有一个包含pandas.DataFrame的类,其中的方法用于返回该DataFrame的列子集,希望获取视图而非副本。代码示例如下:

import pandas as pd
import numpy as np

class Data:
    def __init__(self, path, selected_features):
        df = pd.read_excel(path)
        self._features = df[selected_features].astype("float64")  # 原数据仅包含int64和float64类型

    def features(self):
        return self._features.iloc[:, 0:2]  # 仅返回前2列作为示例

通过np.shares_memory()验证发现返回的是副本:

data = Data(path, selected_features)
print(np.shares_memory(data._features, data.features()))
# 输出: False
print(np.shares_memory(data._features, data._features.iloc[:,0:2]))
# 输出: False

使用.loc也得到相同结果。请问为何返回副本,如何让它返回视图?


原因分析

1. astype操作强制生成副本

初始化时执行的.astype("float64")是核心原因之一:即使原数据包含float64类型,只要存在int64列,转换为统一float64类型时必须创建新内存块——int和float的存储格式完全不同,无法在原内存空间直接修改,因此self._features本身就是原DataFrame的副本。

2. 列子集的内存布局限制

通过iloc或loc选取列子集时,Pandas是否返回视图取决于底层数据的内存连续性。即使self._features的所有列都是float64,由于它来自之前的副本操作,Pandas无法确保其内存布局的连续性,因此默认生成副本以保证后续操作的稳定性。


解决方案

方法1:直接操作底层numpy数组

既然self._features的所有列都是float64类型,其底层存储为连续的numpy数组,直接对数组进行切片(numpy切片默认返回视图),再封装为DataFrame即可:

def features(self):
    # 获取原DataFrame底层数组的列切片视图
    arr_view = self._features.values[:, 0:2]
    # 用原列名和索引创建新DataFrame,共享内存
    return pd.DataFrame(arr_view, columns=self._features.columns[:2], index=self._features.index)

验证:

data = Data(path, selected_features)
print(np.shares_memory(data._features.values, data.features().values))
# 输出: True

方法2:使用pd.DataFrame.view()

利用Pandas的view方法创建共享内存的视图,前提是子集数据类型与原DataFrame一致:

def features(self):
    subset = self._features.iloc[:, 0:2]
    # 创建同类型的视图
    return subset.view(dtype='float64')

注意:此方法要求子集的数据类型必须与原DataFrame完全一致,否则会抛出类型不匹配的错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 02:29:58