从Pandas数据框中选择数据时,有时会返回一个视图,有时会返回一个副本。 虽然这背后有一个逻辑,有没有办法强制Pandas 显式地返回一个视图或副本?
答案 0 :(得分:5)
您的问题分为两部分:(1)如何制作视图(请参阅本答案的底部),以及(2)如何制作副本。
我将演示一些示例数据:
import pandas as pd
df = pd.DataFrame([[1,2,3],[4,5,6],[None,10,20],[7,8,9]], columns=['x','y','z'])
# which looks like this:
x y z
0 1 2 3
1 4 5 6
2 NaN 10 20
3 7 8 9
如何制作副本:一种选择是在执行任何操作后显式复制DataFrame。例如,假设我们选择的是没有NaN的行:
df2 = df[~df['x'].isnull()]
df2 = df2.copy()
然后,如果您修改df2中的值,您会发现修改不会传播回原始数据(df),并且Pandas不会警告"正在尝试在副本上设置值来自DataFrame"
的切片df2['x'] *= 100
# original data unchanged
print(df)
x y z
0 1 2 3
1 4 5 6
2 NaN 10 20
3 7 8 9
# modified data
print(df2)
x y z
0 100 2 3
1 400 5 6
3 700 8 9
注意:您可以通过明确复制来降低性能。
如何忽略警告:或者,在某些情况下,您可能不关心是否返回视图或副本,因为您的目的是永久修改数据并且永远不会返回原始数据。在这种情况下,您可以取消警告并快速前进(只是不要忘记您已将其关闭,并且原始数据可能会或可能不会被您的代码修改,因为df2可能是也可能不是副本):
pd.options.mode.chained_assignment = None # default='warn'
有关详细信息,请参阅How to deal with SettingWithCopyWarning in Pandas?
上的答案 如何制作视图:Pandas会随时随地隐式地制作视图。关键是要使用df.loc[row_indexer,col_indexer]
方法。例如,要将列y
的值乘以100仅适用于列x
不为空的行,我们会写:
mask = ~df['x'].isnull()
df.loc[mask, 'y'] *= 100
# original data has changed
print(df)
x y z
0 1.0 200 3
1 4.0 500 6
2 NaN 10 20
3 7.0 800 9