2016-12-26 63 views
1

我有一个简单的DF与收入和成本数字。在我的情况下,成本可能是负面的。lambda函数与多个ifs使用熊猫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条件。

+0

这与创建'lambda'函数的问题无关,但'&'是Python中的按位运算符。当你做逻辑时,你需要''和'运算符 - (这似乎是你想要的)。两个操作符对布尔值“True”和“False”的作用相同,但如果在操作中包含其他“真值”,则不会总是执行相同的操作(例如,将'1&2'与' 1和2')。 – Blckknght

回答

2

熊猫矢量

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'] < 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'] <= 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它少,我们是好的。因此,在开始的功能。

+1

很好的解释。我该如何给你赏赐呢? :P – MYGz

+1

直到2天才能获得赏金。没有必要,但我很欣赏这种姿态(当然,如果你坚持:我不能阻止你.-) – piRSquared

+0

太棒了。非常精彩!!! – codingknob

1

请勿使用apply。这是非常缓慢的。使用嵌套的地方。

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