使用 pandas df 的具有多个 if 的 lambda 函数

Posted

技术标签:

【中文标题】使用 pandas df 的具有多个 if 的 lambda 函数【英文标题】:lambda function with multiple ifs using pandas df 【发布时间】:2017-05-10 14:24:23 【问题描述】:

我有一个包含收入和成本数据的简单 df。就我而言,成本可能是负数。

我想按如下方式计算收入成本比:

if ((x['cost'] < 0) & (x['rev'] >=0 )):
   x['r_c_ratio'] = (x['rev'] + abs(x['cost'])) / abs(x['cost'])
elif((x['cost'] > 0) & (x['rev'] <=0 )):
   x['r_c_ratio'] = (x['cost'] + abs(x['rev'])) / x['cost']
else:
   x['r_c_ratio'] = x['rev'] / x['cost']

如何在 lambda 函数中实现这一点?

df['revenue_cost_ratio'] = df.apply(lambda x:....

根据这个link,lambda 语法是:

lambda x: True if x % 2 == 0 else False

这只允许一个 else 条件。

【问题讨论】:

这与您关于创建lambda 函数的问题无关,但&amp; 是Python 中的位与运算符。当您执行逻辑与(这似乎是您想要的)时,您需要 and 运算符。这两个运算符对于布尔值 TrueFalse 的工作方式相同,但如果您在操作中涉及其他“真实”值(例如比较 1 &amp; 21 and 2 )。 【参考方案1】:

熊猫矢量化

r = x.rev.div(x.cost)
r.abs().add(r < 0).rename('revenue_cost_ratio')

numpy 矢量化 顺便说一句,我会用这个

r = x.rev.values / x.cost.values
pd.Series(np.abs(r) + (r < 0), x.index, name='revenue_cost_ratio')

如果你坚持使用 lambda

f = lambda x: (x.rev * x.cost < 0) + abs(x.rev / x.cost)
x['revenue_cost_ratio'] = x.apply(f)

让我们看看你的 3 个案例

案例 1

if ((x['cost'] < 0) & (x['rev'] >=0 )):
   x['r_c_ratio'] = (x['rev'] + abs(x['cost'])) / abs(x['cost'])

x['cost'] &lt; 0abs(x['cost']) 只是-1 * x['cost'] 所以这可以简化为

(x['rev'] - x['cost']) / -x['cost']

(x['cost'] - x['rev']) / x['cost']

案例 2

elif((x['cost'] > 0) & (x['rev'] <=0 )):
   x['r_c_ratio'] = (x['cost'] + abs(x['rev'])) / x['cost']

x['rev'] &lt;= 0abs(x['rev']) 只是-1 * x['rev'] 所以这可以简化为

(x['cost'] - x['rev']) / x['cost']

哇,这和案例一一样!但我们可以将其进一步简化为

1 - x['rev'] / x['cost']

我们什么时候使用它?似乎仅当 x['rev']x['cost'] 为负但不是两者都为负时。好吧,只有当该比率为负时才会发生这种情况。

案例 3

x['rev'] / x['cost']

再来一次!多么幸运!这看起来很像1 - x['rev'] / x['cost']

因此,如果我们预先计算 x['rev'] / x['cost'],测试它的负值并返回它或减去 1,我们很好。因此是一开始的功能。

【讨论】:

很好的解释。我怎么给你赏金呢? :P 直到 2 天才能发放赏金。没必要,但我很欣赏这个姿态(当然,如果你坚持,我不能阻止你:-)【参考方案2】:

不要使用应用。它非常慢。使用嵌套的 where。

np.where((x['cost'] < 0) & (x['rev'] >=0 ),  (x['rev'] + abs(x['cost'])) / abs(x['cost']),
    np.where((x['cost'] > 0) & (x['rev'] <=0 ), (x['cost'] + abs(x['rev'])) / x['cost'], 
             x['rev'] / x['cost']))

【讨论】:

以上是关于使用 pandas df 的具有多个 if 的 lambda 函数的主要内容,如果未能解决你的问题,请参考以下文章

如何使用具有多个源列的 pandas_udf 将多个列添加到 pyspark DF?

Pandas:过滤具有多个字符串条件的行[重复]

将多个键上的 pandas 数据帧映射为列或 multiIndex

在具有多个 if 语句的 Pandas Lambda 函数中使用 Apply

根据 pandas df 中的多个条件映射不同的数据帧

在 Pandas 中重命名多个列