使用pandas df的多个ifs的lambda函数

时间:2016-12-26 02:10:20

标签: python pandas lambda

我有一个简单的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

这只允许其他条件。

2 个答案:

答案 0 :(得分:2)

pandas vectorized

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

numpy vectorized
顺便说一句,我使用这个

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'] < 0时,abs(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'] <= 0时,abs(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,我们就是好的。因此,开头的功能。

答案 1 :(得分:1)

不要使用申请。这非常慢。使用嵌套的地方。

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']))