在pandas数据帧中将0替换为数组中看到的最后一个值(类似于具有NaN值的fillna方法)

时间:2017-12-04 21:51:42

标签: python arrays python-3.x pandas numpy

我一直在尝试从两个初始布尔数组(df1和df2)创建一个新的布尔数组,遵循以下规则:

- 如果在df1中看到最后一个True值,则df3中的值为True - 如果在df2中看到最后一个True值,则df3中的值为False

我找到了一种方法,通过减去两个数组,然后用NaN值重新计算0值,使用.fillna方法填充NaN值,最后将-1值重新设置为0. / p>

代码看起来像这样(以随机数组为例):

将pandas导入为pd 将matplotlib.pyplot导入为plt 导入numpy为np

df1 = pd.Series((1,1,1,0,0,0,0,0,0,0,
                 0,0,0,0,1,0,0,1,0,0,
                 0,0,0,0,0,1,1,1,0,0,
                 0,0,0,0,0,0,0,0,0,0,
                 0,0,0,1,1,1,0,0,0,0))


df2 = pd.Series((0,0,0,0,0,0,1,1,0,0,
                 0,0,0,0,0,0,0,0,0,0,
                 1,0,0,0,0,0,0,0,0,0,
                 0,0,0,1,0,0,1,0,0,0,
                 0,0,0,0,0,0,0,0,0,0))

df3 = df1-df2
df3 = df3.replace(0,np.nan).fillna(method='ffill')
df3 = df3.replace(-1,0)

它完成了技巧并返回了我想要的数组,但似乎没有优化像这样多次重新设置值,并使用fillna方法来做我想要的。

有没有人知道如何更“正确”地执行此操作,并且如果有一个类似于fillna的方法,但是除了NaN之外的其他值?

优化对于这个问题非常重要,因为我会花很多时间来完成这个过程。

1 个答案:

答案 0 :(得分:1)

这应该更快一些(200,000行大约6倍,但当然要检查一下)。 import numpy as np之后:

arr = np.select( [df1==1,df2==1], [1,0], default=np.nan )
ser = pd.Series( arr ).ffill()

如果您不熟悉np.select,它与np.where非常相似,但允许多种条件。你也可以做一个嵌套的np.where,但这更具可读性。

以下是arr,允许您执行简单的ffill而无需使用replace两次的原因是,您有nan而不是零。

array([  1.,   1.,   1.,  nan,  nan,  nan,   0.,   0.,  nan,  nan,  nan,
        nan,  nan,  nan,   1.,  nan,  nan,   1.,  nan,  nan,   0.,  nan,
        nan,  nan,  nan,   1.,   1.,   1.,  nan,  nan,  nan,  nan,  nan,
         0.,  nan,  nan,   0.,  nan,  nan,  nan,  nan,  nan,  nan,   1.,
         1.,   1.,  nan,  nan,  nan,  nan])

你可以通过存储df1和amp;来获得更快的速度。 df2作为numpy数组而不是数据帧/系列,但我认为它不会太重要。

如果速度确实是一个问题,你应该尝试在numpy而不是pandas(如果可能的话)中做所有事情,但我不确定pandas ffill是否有一个好的numpy模拟。