【问题标题】:Does pandas loc generates a copy in itself but it is a view with assignment?pandas loc 本身是否会生成一个副本,但它是一个带有分配的视图?
【发布时间】:2022-01-27 01:09:12
【问题描述】:

问题

.loc 是否根据上下文同时生成视图和副本?

背景

对 pandas .loc 的行为有点困惑,因为我认为它应该生成一个视图。但是,它看起来会在下面的示例中生成一个副本。

import numpy as np
import pandas as pd

df_for_view = pd.DataFrame(np.random.choice(10, (3, 5)), columns=list('ABCDE'))
back_for_view = df_for_view
print(back_for_view)
---
   A  B  C  D  E
0  1  5  3  7  3
1  3  3  8  3  2
2  1  7  6  8  4

使用生成副本的.loc

df_for_view = df_for_view.loc[:, ['B']]
print(df_for_view.values.base is back_for_view.values.base)
---
False   # <--- .loc has generated a copy because the base is different

更新生成的.loc不反映。

df_for_view.loc[:, :] = -1
print(back_for_view)
---
   A  B  C  D  E
0  1  5  3  7  3
1  3  3  8  3  2
2  1  7  6  8  4

另一方面,如果更新赋值发生在同一行,它看起来.loc生成了一个视图。

df_for_view = pd.DataFrame(np.random.choice(10, (3, 5)), columns=list('ABCDE'))
back_for_view = df_for_view

print(f"df_for_view is \n{df_for_view}\n")
print("updating...")
df_for_view.loc[:, ['B']] = -1

print(f"df_for_view is \n{df_for_view}\n")
print(f"back_for_view is \n{back_for_view}\n")

print(df_for_view.values.base is back_for_view.values.base)
print(df_for_view.loc[:, ['B']].values.base is back_for_view.values.base)

结果:

df_for_view is 
   A  B  C  D  E
0  7  7  0  5  1
1  7  3  7  3  6
2  3  0  5  4  8

updating...
df_for_view is 
   A  B  C  D  E
0  7 -1  0  5  1
1  7 -1  7  3  6
2  3 -1  5  4  8

back_for_view is 
   A  B  C  D  E
0  7 -1  0  5  1
1  7 -1  7  3  6
2  3 -1  5  4  8

True
False

那么,.loc 生成视图或副本取决于它发生的上下文?

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    有趣的问题,似乎更多的是关于分配与复制。 df_for_view.loc[:, ['B']] 本质上是一个新的数据框,正如

    所证明的那样
    print(df_for_view.loc[:, ['B']].values.base is back_for_view.values.base)
    
    False
    

    所以df_for_view = df_for_view.loc[:, ['B']]

    可能是其他任何类似的 df

    df_for_view = df_any
    

    这是一个数据框副本。

    现在,这是为 df 中的每个元素分配 -1,一个整数:

    df_for_view.loc[:, :] = -1 
    

    本来可以

    df_for_view.at[:, :] = -1 
    

    并具有相同的效果,甚至类似:

    df_for_view.loc[:,:] = df_for_view.loc[2:2]
    

    总而言之,我认为不同之处在于,在第一种情况下,loc 生成一个要复制到另一个上的新数据帧,而在第二种情况下,它用于引用数据帧中的每个元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-11
      • 1970-01-01
      • 2018-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-06
      相关资源
      最近更新 更多