首页 > 解决方案 > 为 Pandas 列编写一个可选的可执行(惰性)函数

问题描述

我正在尝试编写一个带有可选“可调用”列的脚本。

基本要点:

我们有一个包含大约 25 列的基本 DataFrame。平均长度 ~ 3000 行。可以在调用时添加多个附加属性 - 最多可以进行 80 个附加计算。

但是,只有当某些计算通过多个分支成功(由用户选择)时,我们才会进行后续添加。

问题:我想在这里将所有这些附加列定义为延迟执行的函数,即仅在需要时执行,而不是预先计算所有这 80 列并添加到 DataFrame。

对于用户来说,它仍然会提供一个结果。

lambda函数会有帮助吗?

df = df.assign(IsDate = lambda x:(x.dt < date(2021,11,1)))

应该延迟执行列 ['IsDate'] 的位置。但是,下面的(是否等效)不会是懒惰的。

df['IsDate'] = x.dt < date(2021,11,1)

我不确定我的问题是否清楚。

标签: pandasdataframe

解决方案


问题:我想在这里将所有这些附加列定义为延迟执行的函数,即仅在需要时执行,而不是预先计算所有这 80 列并添加到 DataFrame。

为什么不创建将所需列添加到作为参数传递的 DataFrame 的函数?并且只有在满足给定条件时才调用这些函数。

df = df.assign(IsDate = lambda x:(x.dt < date(2021,11,1)))

df['IsDate'] = x.dt < date(2021,11,1)

这两行是等价的。第一个不是惰性执行,在行执行后立即创建列。

你不想要类似的东西吗

# if condition 1 is satisfied compute and add the 'IsDate' column to df
if cond_1: 
  df['IsDate'] = x.dt < date(2021,11,1)
  # if also condition 2 is satisfied, add 'new_column1'
  if cond_2:
  df['new_column1']  = .... 
     
if cond_3:
  df['new_column2']  = .... 

当然,你不应该嵌套太多的 if 语句。我确信有更好的方法来处理流量控制,具体取决于您到底想要什么,我并不完全理解。

对于更复杂的计算,您可以将逻辑放在函数中

def add_isdate(df):
   """ function that adds 'Isdate' to df. Mutates df in-place."""
   
   df['IsDate'] = x.dt < date(2021,11,1)

def add_related_cols(df):
   """ function that computes several similar calculations 
       and add them as columns to df. Mutates df in-place."""

   df['col1'] = (...)
   # do other computations 
   df['col2'] = (...)
   # (...)

df = pd.DataFrame(...)

# Add 'IsDate' to df (in-place) if cond_1 is met 
if cond_1:
  add_isdate(df)

# if cond_2 is met, do a bunch of computations and add them to df (in-place)
if cond_2:
  add_related_cols(df)

如果您不希望函数就地添加列,您可以创建传递的 DataFrame 的副本,并返回另一个带有附加列的 DataFrame

def add_column_not_inplace(df):
   """ computes new column(s). Returns a new 
       DataFrame with the additional column(s) """
   # make a copy of the DataFrame passed
   df_copy = df.copy()
   
   # compute and add the new columns
   df_copy['new_col'] = (...)
   # (...)
   
   # returns the copy of the original df with the new columns 
   return df_copy


df = pd.DataFrame(...)

# if cond_1 is met, add the column to df. 
# Assign the result to df1 as the functions doesn't act in-place
if cond_1:
  df1 = add_column_not_inplace(df)

推荐阅读