Pandas数据帧中零点的除法算法

时间:2017-01-12 16:36:59

标签: python pandas dataframe

说我有一个数据框:

 a   b
-5   1
 4  -2
 0   0
 1   0
 0   3

我想分开: x = df.a / df.b

显然,我会得到除以零错误或inf的结果。但是我想用这样的算法进行除法(伪代码):

def CalcRatio(a, b):
    ratio = a / b
    if (isinf(ratio) or isnan(ratio)):
        ratio = (1 + a) / (1 + b)
    return ratio

我怎么能用熊猫做到这一点?感谢。

2 个答案:

答案 0 :(得分:3)

您可以在代码中使用np.isinfnp.isnan来按行apply执行您想要的操作:

In [207]:

def CalcRatio(a, b):
    ratio = a / b
    if (np.isinf(ratio) or np.isnan(ratio)):
        ratio = (1 + a) / (1 + b)
    return ratio
​
df.apply(lambda x: CalcRatio(x['a'],x['b']), axis=1)

Out[207]:
0   -5.0
1   -2.0
2    1.0
3    2.0
4    0.0
dtype: float64

矢量化方法是使用np.where并传递True情况中的条件以返回替代结果,否则执行除法:

In [208]:
np.where(np.isinf(df['a']/df['b']) | pd.isnull(df['a']/df['b']), (1 + df['a']) / (1 + df['b']), df['a']/df['b'])

Out[208]:
array([-5., -2.,  1.,  2.,  0.])

<强>定时

对于5K行df:

In [213]:
%timeit df.apply(lambda x: CalcRatio(x['a'],x['b']), axis=1)
%timeit np.where(np.isinf(df['a']/df['b']) | pd.isnull(df['a']/df['b']), (1 + df['a']) / (1 + df['b']), df['a']/df['b'])

1 loops, best of 3: 225 ms per loop
1000 loops, best of 3: 1.32 ms per loop

我们在这里可以看到,矢量化方法比apply更好地扩展,这只是迭代每一行,这里快〜170倍,我希望numpy方法能够更好地扩展到大型数据集

新时间

In [218]:
%%timeit 
d1 = df.a / df.b
d2 = df.a.add(1) / df.b.add(1)    ​
d1.replace(np.inf, np.nan).fillna(d2)

1000 loops, best of 3: 1.06 ms per loop

In [219]:
%%timeit
d1 = df.add(df.b == 0, 0)
d1.a / d1.b

1000 loops, best of 3: 691 µs per loop

以上是@ piRSquared的答案明显更快

答案 1 :(得分:2)

你可以采用这种方法

d1 = df.a / df.b
d2 = df.a.add(1) / df.b.add(1)

d1.replace(np.inf, np.nan).fillna(d2)

0   -5.0
1   -2.0
2    1.0
3    2.0
4    0.0
dtype: float64

另一种方法
df.b == 0为零(显然)时,True评估为b。但是,当您添加此列时,它只会将1添加到b为零的行中。然后你做分工。

d1 = df.add(df.b == 0, 0)
d1.a / d1.b