Python 2.7 避免链式选择

Python 2.7 避免链式选择,python-2.7,pandas,Python 2.7,Pandas,我正在尝试确定“最佳实践”来执行以下操作,而不会导致设置CopyWarning。我正在使用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'] == 'bl

我正在尝试确定“最佳实践”来执行以下操作,而不会导致设置CopyWarning。我正在使用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中生成了一个带有CopyWarning的
设置,但其行为与我所希望的一样(即
cars
df未被修改)

  • 执行
    选择_blue_cars
    以使后续代码不会触发此警告的最佳方法是什么

  • 我应该到处使用
    .copy()

    return df[df['color'] == 'blue'].copy()
    
  • (旁白)
    copy()
    的性能怎么样
最后,我想链接一些简单的转换函数,如
选择\u blue\u cars

blue_fords = select_fords(select_blue_cars(cars))
Edit:仔细考虑后,我认为我正在寻找一种转换,它从数据帧中选择一个副本,而不显式调用
.copy()
。这样我就可以编写函数对df进行小的转换并将它们链接起来

例如,转置
df.T
给出了一个新的数据帧。无需调用
.copy()


看起来,在选择的情况下,这个模式需要
.copy()

我认为这仍然是熊猫比较容易混淆的部分之一。你实际上问了两三个问题,答案可能没有你想象的那么简单。因此,我将做一个简化的假设,即将所有内容都保存在一个数据集中(如果不是,那也没什么大不了的),并给出一个简单的答案

要执行的操作(伪代码):

price=10000如果颜色==蓝色

最简单的方法实际上是使用numpy
where()

cars['price']=np.where(cars['color']='blue',10000,np.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

绕过
设置CopyWarning
取决于您计划保留子集的时间。如果您只想简单地看一下特定颜色内的价格,然后返回到整体数据框,那么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

settingwithcopywarning用于提醒您可能正在修改数据帧的副本。这是来自
蓝车['price']=10000行的警告吗?你应该试着用blue_cars.loc代替。如果这是您明确的意图,那么警告只是建议您函数可能没有按照您的想法执行。我只是尝试了您的代码,没有得到警告。到底是哪一行?这是我在JohnE设定价格的最后一行。熊猫的版本很重要。我在15.3收到警告。我想我需要做的就是希望有人能纠正我!调用两个方法来执行此操作感觉有些不对劲。在我的编辑中,
cars.T
或类似的转换不需要在上面加上
.copy()
。感谢您的回答。最终将使用.copy()而不是实际复制两次?您的回答很有帮助,因为它表明我可能无法使用单个数据帧方法来完成我想要的任务。在这种情况下,我不想修改原始数据帧,我想选择它的一部分并独立使用它。现在可能更重要的一点是熊猫不应该以这种方式使用,我应该重构东西,这样我就可以修改单个数据帧了!
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