微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在pandas dataframe中写一个用户定义的fillna函数,用条件填充np.nan不同的值

考虑以下pandas数据帧:

import pandas as pd

change = [0.475, 0.625, 0.1, 0.2, -0.1, -0.75, 0.1, -0.1, 0.2, -0.2]
position = [1.0, 1.0, nan, nan, nan, -1.0, nan, nan, nan, nan]
date = ['20150101', '20150102', '20150103', '20150104', '20150105', '20150106', '20150107', '20150108', '20150109', '20150110']
pd.DataFrame({'date': date, 'position': position, 'change': change})

输出

     date        change       position    
    20150101      0.475          1
    20150102      0.625          1
    20150103      0.1            np.nan
    20150104      0.2            np.nan
    20150105      -0.1           np.nan
    20150106      -0.75          -1
    20150107      0.1            np.nan
    20150108      -0.1           np.nan
    20150109      0.2            np.nan
    20150110      -0.2           np.nan

我想用以下规则填写:

>对于“位置”值为np.nan的行,如果“change”的值与position的最后一个非null值具有相同的符号(change * position> 0,例如0.1 * 1和0.2 * 1> 0 ),我们用最后一个非空值填充.
>对于“位置”值为np.nan的行,如果“change”的值与position的最后一个非null值相同的符号(change * position< = 0,如-1 * 0.1),我们fillna 0.
>一旦np.nan填充为0,则以下np.nan也将填充0.

以下是样本数据框的预期结果:

     date        change       position    
    20150101      0.475          1
    20150102      0.625          1
    20150103      0.1            1
    20150104      0.2            1
    20150105      -0.1           0
    20150106      -0.75          -1
    20150107      0.1            0
    20150108      -0.1           0
    20150109      0.2            0
    20150110      -0.2           0

编辑:

我开发的方法如下:

while(any(np.isnan(x['position']))):
    conditions = [(np.isnan(x['position'])) & (x['position'].shift(1) * x['change'] > 0),
                  (np.isnan(x['position'])) & (x['position'].shift(1) * x['change'] <= 0)]
    choices = [x['position'].shift(1), 0]
    x['position'] = np.select(conditions, choices, default=x['position'])

但正如你所看到的,它不是很令人满意,而且如果你有80,000,000行数据则非常慢.

有什么建议?谢谢您的帮助!

解决方法:

我认为你的代码非常可靠,主要问题是你需要多次迭代它. shift()一次只返回一行,但是如果你把它改成fillna(method =’ffill’)那么你基本上得到一个无限制的移位数但只需要做一次而不是多次迭代(如何许多迭代将取决于您的数据).

conditions = [
    (np.isnan(x['position'])) & (x['position'].fillna(method='ffill')*x['change']>0),
    (np.isnan(x['position'])) & (x['position'].fillna(method='ffill')*x['change']<=0)]

但我相信你可以更进一步,通过在最后添加一个fillna消除时间:

conditions = [
    (np.isnan(x['position'])) & (x['position'].fillna(method='ffill')*x['change']>0),
    (np.isnan(x['position'])) & (x['position'].fillna(method='ffill')*x['change']<=0)]

choices=[x['position'].shift(1),0]
x['position'] = np.select(conditions,choices,default=x['position'])

x['position'] = x['position'].fillna(method='ffill')

在您的示例数据上,第一次更改比您的代码快2倍,第二次更改大约是4倍.我得到了与你相同的答案,但当然你会想要在真实数据上验证这一点.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐