2016-12-26 30 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']))