2016-11-08 44 views
1

我想根據第三列中的條件將DataFrame的一列中的值乘以另一列中的值。例如:多個系列與另一個系列的條件乘法

data = pd.DataFrame({'a': [1, 33, 56, 79, 2], 'b': [9, 12, 14, 5, 5], 'c': np.arange(5)}) 
data.loc[data.a > 10, ['a', 'b']] *= data.loc[data.a > 10, 'c'] 

我想此做的是通過相應的(同一行)的「c」的基於條件的值乘以兩個「一」和「b」的值。但是,上面的代碼只會導致NaN值在期望的範圍內。

我發現的最接近的解決方法已經做到這一點:

data.loc[data.a > 10, ['a', 'b']] = (data.loc[data.a > 10, ['a', 'b']].as_matrix().T * data.loc[data.a > 10, 'c']).T 

其作品,但它好像有我就是缺少一個更好的(更Python)的方式。

回答

4

您可以使用mul(..., axis=0)方法:

In [122]: mask = data.a > 10 

In [125]: data.loc[mask, ['a','b']] = data.loc[mask, ['a','b']].mul(data.loc[mask, 'c'], 0) 


In [126]: data 
Out[126]: 
    a b c 
0 1 9 0 
1 33 12 1 
2 112 28 2 
3 237 15 3 
4 2 5 4 
2

這裏是一個替代使用Series.where()有條件地更新值:

data[['a', 'b']] = data[['a', 'b']].apply(lambda m: m.where(data.a <= 10, m*data.c)) 

enter image description here

2

使用update

data.update(data.query('a > 10')[['a', 'b']].mul(data.query('a > 10').c, 0)) 

data 

enter image description here

1

那麼它似乎NumPy的可能是這裏的替代 -

arr = data.values 
mask = arr[:,0] > 10 
arr[mask,:2] *= arr[mask,2,None] 

我們只是提取的values爲數組,這是一個視圖到數據幀,讓我們可以在陣列上工作並且更新將自動反映在數據框中。這裏有一個樣品運行顯示進度 -

In [507]: data # Input dataframe 
Out[507]: 
    a b c 
0 1 9 0 
1 33 12 1 
2 56 14 2 
3 79 5 3 
4 2 5 4 

使用建議的代碼 -

In [508]: arr = data.values 

In [509]: mask = arr[:,0] > 10 

In [510]: arr[mask,:2] *= arr[mask,2,None] 

驗證與數據幀結果 -

In [511]: data 
Out[511]: 
    a b c 
0 1 9 0 
1 33 12 1 
2 112 28 2 
3 237 15 3 
4 2 5 4 

讓我們試着通過我們的確是其他的方式來驗證在那裏工作 -

In [512]: np.may_share_memory(data,arr) 
Out[512]: True 
+0

這並不能保證這些實際上是一種觀點;他們碰巧因爲你有一個單一的dtype,但即使可能不是特別是如果列錯誤創建迭代 – Jeff

+0

@Jeff謝謝!請牢記這一點,有用的信息! – Divakar

0
# %% 
import pandas as pd 
import numpy as np 

data = pd.DataFrame({'a': [1, 33, 56, 79, 2], 
        'b': [9, 12, 14, 5, 5], 
        'c': np.arange(5)}) 

(data.loc[data.a>10, ['a','b']]\ 
.T * data.loc[data.a>10, 'c'])\ 
.T.append(data.loc[data.a<=10, ['a','b']])\ 
.T.append(data.c).T.sort() 
# %% 

Out[17]: 
    a b c 
0 1 9 0 
1 33 12 1 
2 112 28 2 
3 237 15 3 
4 2 5 4