说我有一个数据框:
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
我怎么能用熊猫做到这一点?感谢。
答案 0 :(得分:3)
您可以在代码中使用np.isinf
和np.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