【问题标题】:Python: Lambda if else statement when Pandas Dataframe is emptyPython:当 Pandas Dataframe 为空时的 Lambda if else 语句
【发布时间】:2021-05-19 15:54:27
【问题描述】:

我有一个这样的数据框:

            df
Id    Severity    First Discovered
0      Low            1/1/2021
1      Medium         1/1/2021
2      Medium         1/1/2021

我还在下面定义了一个函数,它有助于创建“目标关闭日期”,它根据相应的“严重性”值向“首次发现”字段添加一定天数。

def get_target_close_date(severity, first_discovered_date):
    '''Adds days to first discovered date depending on severity'''
    if severity == 'Low':
        target_close_date = first_discovered_date + timedelta(days=30)
    elif severity == 'Medium':
        target_close_date = first_discovered_date + timedelta(days=60)

    return target_close_date

通过执行df['Target Close Date'] = df.apply(lambda row: get_target_close_date(row['Severity'], row['First Discovered']), axis=1),数据框正确更新:

         df
Id    Severity    First Discovered    Target Close Date
0      Low            1/1/2021             1/31/2021
1      Medium         1/1/2021             3/2/2021
2      Medium         1/1/2021             3/2/2021

但是,如果数据框为空,则代码不起作用,并且我收到 ValueError: Wrong number of items passed 3, placement 意味着 1。理想情况下,我想在 lambda 函数中添加一个 if else 语句来检查数据框是否为空,例如:

df['Target Close Date'] = df.apply(
  lambda row: get_target_close_date(row['Severity'], row['First Discovered']) if not df.empty else pass, 
    axis=1)

但是,这会一直返回语法错误。我更愿意在 lambda 函数中编写 if else 条件,而不是执行跨越多行的 if else 语句。

【问题讨论】:

  • 你希望... else pass做什么?条件表达式必须计算为 something,所以可能是 ... else None?无论如何,为什么要专门使用 lambda 表达式?
  • 好点。我想我只是不希望发生任何事情(即,如果它是一个空数据框,请不要创建目标关闭日期列,因为这会使其失败)。对于您的第二点,lambda 函数在整个脚本中多次用于许多数据帧,每个数据帧具有不同的名称。至少对我而言,查找和替换 lambda 函数内部的内容比创建需要多次引用数据框名称的多行 if else 语句更容易。

标签: python pandas if-statement lambda apply


【解决方案1】:

一个有用的改变可能是使用一些内置的pandas 工具而不是自定义函数和lambda 表达式。例如,您可以创建一个map

d = {'Low':pd.Timedelta(days=30),
     'Medium':pd.Timedelta(days=60)}

df['Target Close Date'] = df['First Discovered'] + df['Severity'].map(d)

给予:

  Severity First Discovered Target Close Date
0      Low       2021-01-01        2021-01-31
1   Medium       2021-01-01        2021-03-02
2   Medium       2021-01-01        2021-03-02

现在用于处理空 DataFrame。如果df 具有正确的列(SeverityFirst Discovered),这将起作用(Target Close Date 添加为空列)。如果df 完全为空(即没有命名列),这将引发错误。但是你可以添加一个简单的检查:

if df.empty:
    pass
else:
    df['Target Close Date'] = df['First Discovered'] + df['Severity'].map(d)

您可以进一步将其包装在一个函数中以应用于许多不同的 DataFrame:

def process(df):
    d = {'Low':pd.Timedelta(days=30),
         'Medium':pd.Timedelta(days=60)}

    if df.empty:
        pass
    else:
        df['Target Close Date'] = df['First Discovered'] + df['Severity'].map(d)

for df in df_list:
    process(df)

我认为这里的主要好处是使用内置函数而不是依赖循环;对于更大的数据集,它应该会更高效(例如,请参阅here)。

【讨论】:

    【解决方案2】:

    使用内置的 Pandas 工具和地图功能会导致警告关于 PerformanceWarning: 添加/减去 object-dtype 数组到 TimedeltaArray 未矢量化,但它似乎有效。但是,我认为问题出在 lambda 函数内部;无法理解对数据框的引用,所以我实际上只需要检查行本身是否为空。下面的代码解决了这个问题。

    df['Target Close Date'] = df.apply(
      lambda row: None if row.empty else get_target_close_date(row['Severity'], row['First Discovered']),
        axis=1)
    

    【讨论】:

      猜你喜欢
      • 2023-04-03
      • 2019-04-09
      • 1970-01-01
      • 2019-03-22
      • 1970-01-01
      • 2021-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多