我正在尝试确定“最佳做法”,以便在不产生SettingWithCopyWarning
的情况下执行以下操作。我正在使用python 2.7和pandas 15.2
我想要做的是选择一个数据帧,然后将此选择用作新的数据帧,而不必冒险修改原始数据帧。这是我正在做的一个例子:
import pandas as pd
def select_blue_cars(df):
"""Returns a new dataframe of blue cars"""
return df[df['color'] == 'blue']
cars = pd.DataFrame({'color': ['blue', 'blue', 'red'], 'make': ['Ford', 'BMW', 'Ford']})
blue_cars = select_blue_cars(cars)
blue_cars['price'] = 10000
以上在当前的pandas中生成SettingWithCopyWarning
,但其他行为与我想要的一样(即cars
df尚未修改。)
实施select_blue_cars
的最佳方式是什么,以便后续代码不会触发此警告?
我应该到处使用.copy()
吗?
return df[df['color'] == 'blue'].copy()
copy()
的表现如何? 最终我想链接简单的变换函数,如select_blue_cars
:
blue_fords = select_fords(select_blue_cars(cars))
编辑:考虑到这一点后,我认为我正在寻找一个从数据帧中选择副本而不显式调用.copy()
的转换。这样我就可以编写函数来对df进行少量转换并将它们链接起来。
转置例如df.T
会提供一个新的数据帧。无需拨打.copy()
。
df2 = df.T
df2 = df.T.copy() # no need
看起来,在选择的情况下,此模式需要.copy()
。
答案 0 :(得分:1)
我认为这仍然是大熊猫更令人困惑的部分之一。你实际上问的是2或3个问题,答案可能不如你想象的那么简单。因此,我将做出简化的假设,即您只需将所有内容保存在一个数据集中(如果不是,它虽然不是那么大),并给出一个简单的答案。
你想做什么(伪代码):
price = 10000 if color == blue
最简单的方法是使用numpy where()
:
cars['price'] = np.where( cars['color'] == 'blue', 10000, np.nan )
color make price
0 blue Ford 10000
1 blue BMW 10000
2 red Ford NaN
你也可以嵌套where()
所以这是非常强大而且简单的条件设置方法。您也可以使用ix/loc/iloc
(尽管您需要先为'price'创建一个空列):
cars.ix[ cars.color == 'blue', 'price' ] = 10000
并简要说明链式索引警告,它主要说的是在设置值时不要试图在左侧做太多:
df[ df.y > 5 ]['x'] = df['z']
这是可以的:
df['x'] = df[ df.y > 5 ]['z']
因为链式索引的结果可能是复制而不是引用,这将导致前者失败而后者失败。您也可以使用ix/loc/iloc
来解决这个问题。
答案 1 :(得分:1)
你如何绕过SettingWithCopyWarning
取决于你计划保留子集的时间。如果您只想简单地查看特定颜色中的价格然后返回到整体数据框,JohnE给出的建议非常好。如果你真的想要保留子集并对其进行一系列单独的分析,那么我通常做的是使用.loc
的子集并明确复制,例如:
subset = df.loc[df['condition'] > 5, :].copy()
在您的代码中,这将是:
import pandas as pd
def select_blue_cars(df):
"""Returns a new dataframe of blue cars"""
return df.loc[df['color'] == 'blue', :].copy()
cars = pd.DataFrame({'color': ['blue', 'blue', 'red'], 'make': ['Ford', 'BMW', 'Ford']})
blue_cars = select_blue_cars(cars)
blue_cars['price'] = 10000