使用 loc 方法获取 DataFrame 的视图

Posted

技术标签:

【中文标题】使用 loc 方法获取 DataFrame 的视图【英文标题】:Obtain a view of a DataFrame using the loc method 【发布时间】:2020-09-05 12:08:37 【问题描述】:

我正在尝试使用 loc 方法获取 pandas 数据帧的视图,但是当我修改原始数据帧时它没有按预期工作。 我想使用 loc 方法提取 DataFrame 的一行/切片,以便在对 DataFrame 进行修改时,切片反映更改。

让我们看看这个例子:

import pandas as pd
import numpy as np
df = pd.DataFrame('ID':np.arange(0,5,2), 'a':np.arange(3), 'b':np.arange(3)).set_index('ID')
df
    a   b
ID      
0   0   0
2   1   1
4   2   2

现在我使用 loc 创建一个切片:

slice1 = df.loc[[2],]
slice1

    a   b
ID      
2   1   1

然后我修改原来的DataFrame:

df.loc[2, 'b'] = 9
df

    a   b
ID      
0   0   0
2   1   9
4   2   2

但不幸的是,我们的切片并没有像我期望的那样反映这种修改:

slice1
    a   b
ID      
2   1   1

我的期望:

    a   b
ID      
2   1   9

我发现了一个使用ilocloc 的组合的丑陋修复,但我希望有更好的方法来获得我期望的结果。 感谢您的帮助。

【问题讨论】:

你的意思是当你改变'df'时,slice1应该自动反映改变?我不认为这是可能的。 是的,这在this doc中提到了 我同意安舒尔的观点。我相信它的设计目的是反过来。您取一个切片,更改切片中的值,然后更新原始 df。 我想知道,因为我可以用 iloc 进行这种修改:slice2 = df.iloc[1:2,:] 然后它反映了 df 更新时的变化。 其实我现在很困惑。我尝试了我在“答案”部分分享的内容。无论如何都不是答案,但希望澄清我的疑问。 【参考方案1】:

免责声明:这不是答案。

我尝试测试如何覆盖链式赋值与 .loc 中的值,参考上面@Quang Hoang 共享的 pandas 文档链接。

这是我尝试过的:

dfmi = pd.DataFrame([list('abcd'),
   list('efgh'),
   list('ijkl'),
   list('mnop')],
   columns=pd.MultiIndex.from_product([['one', 'two'],
   ['first', 'second']]))

df1 = dfmi['one']['second']
df2 = dfmi.loc[:, ('one', 'second')]

df1 和 df2 的输出:

0    b
1    f
2    j
3    n

迭代 1:

value = ['z', 'x', 'c', 'v']
dfmi['one']['second'] = value

输出df1:

0    z
1    x
2    c
3    v

迭代 2:

value = ['z', 'x', 'c', 'v']
dfmi.loc[:, ('one', 'second')] = value

输出df2:

0    z
1    x
2    c
3    v

新集合的分配正在改变这两种情况下的值。

文档说:

引用 1:'方法 2 (.loc) 比方法 1 (chained []) 更受欢迎'

引用 2: '除了简单的情况外,很难预测“getitem”(由链式选项使用)是否会返回视图或副本(这取决于数组的内存布局,pandas没有保证),因此“setitem”(由 .loc 使用)是否会修改 dfmi 或之后立即被丢弃的临时对象。

我无法理解上面的解释。如果 dfmi 中的值可以改变(在我的情况下)并且可能不会改变(比如在 Benoit 的情况下),那么获得结果的方式是什么?不确定我是否在这里遗漏了一点。 寻求帮助

【讨论】:

感谢您的帮助。我稍微修改了您的示例,只取一行:df2 = dfmi.loc[[1], ('one', 'second')],然后将原始 df 修改如下:dfmi.loc[1, ('one', 'second')] = 'z'。然后更改在 df2 切片中不再可见...我也尝试通过直接在切片中更改:df2.loc[1] = 'z' 并且更改不会反馈到 dfmi 数据帧。【参考方案2】:

切片未反映您在原始数据框中所做的更改的原因是因为您首先创建了切片。

创建切片时,您会创建数据切片的“副本”。您没有直接将两者联系起来。

这里的简短回答是您有两​​个选择 1) 首先更改原始 df,然后创建一个切片 2) 不要切片,只需使用 .loc 或 iloc 引用原始 df 进行操作

【讨论】:

【参考方案3】:

你的数据帧和切片的内存地址不同,所以数据帧的变化不会反映在切片中-

答案是改变dataframe中的值,然后切片-

【讨论】:

以上是关于使用 loc 方法获取 DataFrame 的视图的主要内容,如果未能解决你的问题,请参考以下文章

Python pandas.DataFrame.loc函数方法的使用

pandas子集选取的三种方法:[].loc[].iloc[]

使用切片列表从 DataFrame 中获取行

Python 视图与复制错误希望我仅在脚本中使用 .loc

Panadas 中利用DataFrame对象的.loc[,]、.iloc[,]方法抽取数据

Pandas中 DataFrame中添加一行/一列