在函数中'inplace'编辑数据帧,还是返回编辑后的数据帧?



我目前正在开发一个更新数据帧的函数。

我有两种方法可以做到这一点。

示例1:就地编辑。

创建数据帧

mydf = pd.DataFrame({'name':['jim','john','mary','michael'],
'age':[12,46,44,32]})
name  age
0      jim   12
1     john   46
2     mary   44
3  michael   32

我们将进行以下编辑:

  1. 如果名称以j开头,请将'smith'添加到名称中。

  2. 如果年龄大于40,请将其乘以2。

def modify(df):
for i in range(len(df)):
# if age is >40
if df.loc[i,'age'] > 40:
# multiply it by 2
df.loc[i,'age'] = df.loc[i,'age']*2
# get the name
name = df.loc[i,'name']
# if it starts with 'j'
if name[0]=='j':
# add 'smith' to the name
name = name+' '+'smith'
# insert into cell    
df.loc[i,'name'] = name

工作良好。我还没有从函数中返回任何内容,数据帧已经被编辑:

modify(mydf)
print(mydf)
name  age
0   jim smith   12
1  john smith   92
2        mary   88
3     michael   32

示例2我也可以通过返回数据帧来实现这一点,如下所示。我的问题是:有什么区别?一种方法比另一种更可取吗?

def modify(df):
for i in range(len(df)):
if df.loc[i,'age'] > 40:
df.loc[i,'age'] = df.loc[i,'age']*2
name = df.loc[i,'name']
if name[0]=='j':
name = name+' '+'smith'
df.loc[i,'name'] = name
return df

运行功能:

mydf = modify(mydf)
print(mydf)
name  age
0   jim smith   12
1  john smith   92
2        mary   88
3     michael   32

两者都很好。是就地编辑好还是返回dataframe好?

注意:我无法进行矢量化,因为我在实际处理的函数中使用了api。这只是一个玩具示例。

我总是选择返回DataFrame。如果您计划将输出分配给另一个变量(df1 = my_func(df)),请使用df.copy()调用函数,或者确保.copy()位于函数顶部,以免意外修改输入。

DataFrames是可变的,所以和列表一样,它们可以在函数中修改而不返回。然而,当使用返回新对象的pandas函数而不是修改原始对象时,这可能会导致很多混乱。

mydf = pd.DataFrame({'name': ['jim', 'jim'],
'age': [12, 46]})
def modify(df):
df.loc[df.name.eq('jim'), 'age'] = 1000
print(mydf)
#  name  age
#0  jim   12
#1  jim   46
modify(mydf)
print(mydf)
#  name   age
#0  jim  1000
#1  jim  1000

好的,太好了,改变了。但如果我们继续:

def modify2(df):
df.drop_duplicates(inplace=True)
df['age'] = df['age'] + 1
df = pd.concat([df]*4)
df['age'] = df['age'] + 17
modify2(mydf)
print(mydf)
#  name   age
#0  jim  1001

所以这不太好。基本上,该函数只成功地修改了df,直到我们函数的某些部分返回了一个新对象,而不是对原始对象的引用。这是一个非常有问题的问题,需要每个操作都在原地进行,否则就会失败。

我们通常进行np.where,这将加快整个过程

df['name']=np.where(df.name.str[0]=='j',df.name+'smith',df.name)
df['age']=np.where(df.age>40,df.age*2,df.age)
df
Out[90]: 
name  age
0   jimsmith   12
1  johnsmith   92
2       mary   88
3    michael   32

最新更新