多个系列与另一个系列

时间:2016-11-08 19:43:39

标签: python pandas numpy dataframe

我想根据第三列中的条件,将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']

我希望这样做可以增加两者的价值' a'和' b'通过' c'中的相应(相同行)值根据条件。但是,上述代码只会导致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

有效,但似乎有一种更好的(更多Pythonic)方式,我错过了。

5 个答案:

答案 0 :(得分:5)

您可以使用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

答案 1 :(得分: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 :(得分:2)

使用update

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

data

enter image description here

答案 3 :(得分: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]

使用dataframe验证结果 -

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

答案 4 :(得分: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